Merge branch 'master' into 'sprint/191_zhouxin_54352'
# Conflicts: # module/datatable/config.php
This commit is contained in:
@@ -58,7 +58,9 @@ class productEntry extends Entry
|
||||
$product->bugStatistic = $this->loadModel('bug')->getStatistic($productID);
|
||||
break;
|
||||
case 'moduleoptionmenu':
|
||||
$product->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, 'story', 0, '0');
|
||||
$modules = $this->loadModel('tree')->getOptionMenu($productID, $this->param('moduleType', 'story'));
|
||||
$product->moduleOptionMenu = array();
|
||||
foreach($modules as $id => $name) $product->moduleOptionMenu[] = array('id' => $id, 'name' => $name);
|
||||
break;
|
||||
case 'parentstories':
|
||||
$product->parentstories= $this->loadModel('story')->getParentStoryPairs($productID);
|
||||
|
||||
@@ -661,11 +661,11 @@ class baseValidater
|
||||
global $config;
|
||||
if(empty($config->framework->filterXSS)) return $var;
|
||||
|
||||
if(stripos($var, '<script') !== false)
|
||||
if(stripos($var, '<script') !== false or stripos($var, '<script') !== false)
|
||||
{
|
||||
$var = (string)$var;
|
||||
$evils = array('appendchild(', 'createElement(', 'xss.re', 'onfocus', 'onclick', 'innerHTML', 'replaceChild(', 'html(', 'append(', 'appendTo(', 'prepend(', 'prependTo(', 'after(', 'insertBefore', 'before(', 'replaceWith(');
|
||||
$replaces = array('a p p e n d c h i l d (', 'c r e a t e E l e m e n t (', 'x s s . r e', 'o n f o c u s', 'o n c l i c k', 'i n n e r H T M L', 'r e p l a c e C h i l d (', 'h t m l (', 'a p p e n d (', 'a p p e n d T o (', 'p r e p e n d (', 'p r e p e n d T o (', 'a f t e r (', 'i n s e r t B e f o r e (', 'b e f o r e (', 'r e p l a c e W i t h (');
|
||||
$evils = array('appendchild(', 'createElement(', 'xss.re', 'onfocus', 'onclick', 'innerHTML', 'replaceChild(', 'html(', 'append(', 'appendTo(', 'prepend(', 'prependTo(', 'after(', 'insertBefore', 'before(', 'replaceWith(', 'alert(', 'confirm(');
|
||||
$replaces = array('a p p e n d c h i l d (', 'c r e a t e E l e m e n t (', 'x s s . r e', 'o n f o c u s', 'o n c l i c k', 'i n n e r H T M L', 'r e p l a c e C h i l d (', 'h t m l (', 'a p p e n d (', 'a p p e n d T o (', 'p r e p e n d (', 'p r e p e n d T o (', 'a f t e r (', 'i n s e r t B e f o r e (', 'b e f o r e (', 'r e p l a c e W i t h (', 'a l e r t (', 'c o n f i r m (');
|
||||
$var = str_ireplace($evils, $replaces, $var);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class actionModel extends model
|
||||
if($this->post->uid) $this->file->updateObjectID($this->post->uid, $objectID, $objectType);
|
||||
|
||||
/* Call the message notification function. */
|
||||
$this->loadModel('message')->send($objectType, $objectID, $actionType, $actionID, $actor);
|
||||
$this->loadModel('message')->send(strtolower($objectType), $objectID, $actionType, $actionID, $actor);
|
||||
|
||||
/* Add index for global search. */
|
||||
$this->saveIndex($objectType, $objectID, $actionType);
|
||||
|
||||
@@ -418,6 +418,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
|
||||
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
|
||||
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
|
||||
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
|
||||
$lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe;
|
||||
|
||||
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
|
||||
$lang->bug->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
@@ -418,6 +418,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
|
||||
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
|
||||
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
|
||||
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
|
||||
$lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe;
|
||||
$lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed;
|
||||
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
|
||||
$lang->bug->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
@@ -396,6 +396,7 @@ class bugModel extends model
|
||||
elseif($browseType == 'needconfirm') $bugs = $this->getByNeedconfirm($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID);
|
||||
elseif($browseType == 'bysearch') $bugs = $this->getBySearch($productIDList, $branch, $queryID, $sort, '', $pager, $projectID);
|
||||
elseif($browseType == 'overduebugs') $bugs = $this->getOverdueBugs($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID);
|
||||
elseif($browseType == 'assignedbyme') $bugs = $this->getByAssignedbyme($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID);
|
||||
|
||||
return $this->checkDelayedBugs($bugs);
|
||||
}
|
||||
@@ -2646,6 +2647,36 @@ class bugModel extends model
|
||||
->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get by assigned by me.
|
||||
* @param array $productIDList
|
||||
* @param int|string $branch
|
||||
* @param array $modules
|
||||
* @param array $executions
|
||||
* @param string $sort
|
||||
* @param object $pager
|
||||
* @param int $projectID
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByAssignedbyme($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID)
|
||||
{
|
||||
$actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('bug')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($this->app->user->account)->fetchPairs('objectID', 'objectID');
|
||||
return $this->dao->select('*')->from(TABLE_BUG)
|
||||
->where('product')->in($productIDList)
|
||||
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
|
||||
->beginIF($modules)->andWhere('module')->in($modules)->fi()
|
||||
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
|
||||
->andWhere('execution')->in(array_keys($executions))
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('status')->ne('closed')
|
||||
->andWhere('id')->in($actionIDList)
|
||||
->orderBy($sort)
|
||||
->page($pager)
|
||||
->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get by Sonarqube id.
|
||||
*
|
||||
|
||||
@@ -71,7 +71,18 @@ class custom extends control
|
||||
if(($module == 'story' or $module == 'testcase') and $field == 'review')
|
||||
{
|
||||
$this->app->loadConfig($module);
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
|
||||
$this->loadModel('user');
|
||||
|
||||
if($module == 'story')
|
||||
{
|
||||
$this->view->depts = $this->loadModel('dept')->getDeptPairs();
|
||||
$this->view->forceReviewAll = zget($this->config->$module, 'forceReviewAll', 'false');
|
||||
$this->view->forceReview = zget($this->config->$module, 'forceReview', '');
|
||||
$this->view->forceReviewRoles = zget($this->config->$module, 'forceReviewRoles', '');
|
||||
$this->view->forceReviewDepts = zget($this->config->$module, 'forceReviewDepts', '');
|
||||
}
|
||||
|
||||
$this->view->users = $module == 'story' ? $this->user->getCanCreateStoryUsers() : $this->user->getPairs('noclosed|nodeleted');
|
||||
$this->view->needReview = zget($this->config->$module, 'needReview', 1);
|
||||
$this->view->forceReview = zget($this->config->$module, 'forceReview', '');
|
||||
$this->view->forceNotReview = zget($this->config->$module, 'forceNotReview', '');
|
||||
@@ -112,7 +123,16 @@ class custom extends control
|
||||
}
|
||||
elseif($module == 'story' and $field == 'review')
|
||||
{
|
||||
$data = fixer::input('post')->join('forceReview', ',')->get();
|
||||
$data = fixer::input('post')
|
||||
->setDefault('forceReviewAll', 0)
|
||||
->setDefault('forceReviewDepts', '')
|
||||
->join('forceReview', ',')
|
||||
->join('forceReviewRoles', ',')
|
||||
->join('forceReviewDepts', ',')
|
||||
->join('forceReviewAll', ',')
|
||||
->setIF(isset($this->post->forceReviewAll), 'forceReviewAll', 1)
|
||||
->get();
|
||||
|
||||
$this->loadModel('setting')->setItems("system.$module@{$this->config->vision}", $data);
|
||||
}
|
||||
elseif($module == 'story' and $field == 'reviewRules')
|
||||
|
||||
@@ -50,6 +50,10 @@ $lang->custom->oneUnit = "One {$lang->hourCommon}";
|
||||
$lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s";
|
||||
$lang->custom->superReviewers = "Super Reviewer";
|
||||
$lang->custom->kanban = "Kanban";
|
||||
$lang->custom->allUsers = 'All Users';
|
||||
$lang->custom->account = 'Users';
|
||||
$lang->custom->role = 'Role';
|
||||
$lang->custom->dept = 'Dept';
|
||||
|
||||
if($config->systemMode == 'new') $lang->custom->execution = 'Execution';
|
||||
if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon;
|
||||
@@ -181,6 +185,8 @@ $lang->custom->notice->readOnlyOfKanban = "If Change Forbidden, any change on
|
||||
$lang->custom->notice->URSREmpty = 'Custom requirement name can not be empty!';
|
||||
$lang->custom->notice->confirmDelete = 'Are you sure you want to delete it?';
|
||||
$lang->custom->notice->confirmReviewCase = 'Set the case in Wait to Normal?';
|
||||
$lang->custom->notice->storyReviewTip = 'After selecting by individual, position, and department, take the union of these three filters. ';
|
||||
$lang->custom->notice->selectAllTip = 'After selecting all people, the reviewers will be emptied and grayed out while hiding their positions and departments.';
|
||||
|
||||
$lang->custom->notice->indexPage['product'] = "ZenTao 8.2+ has Product Home. Do you want to go to Product Home?";
|
||||
$lang->custom->notice->indexPage['project'] = "ZenTao 8.2+ has Project Home. Do you want to go to Project Home?";
|
||||
|
||||
@@ -50,6 +50,10 @@ $lang->custom->oneUnit = "一个{$lang->hourCommon}";
|
||||
$lang->custom->convertRelationTitle = "请先设置{$lang->hourCommon}转换为%s的换算系数";
|
||||
$lang->custom->superReviewers = "超级评审人";
|
||||
$lang->custom->kanban = "看板";
|
||||
$lang->custom->allUsers = '所有人员';
|
||||
$lang->custom->account = '人员';
|
||||
$lang->custom->role = '职位';
|
||||
$lang->custom->dept = '部门';
|
||||
|
||||
if($config->systemMode == 'new') $lang->custom->execution = '执行';
|
||||
if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon;
|
||||
@@ -181,6 +185,8 @@ $lang->custom->notice->readOnlyOfKanban = "禁止修改后,已关闭{$lang-
|
||||
$lang->custom->notice->URSREmpty = '自定义需求名称不能为空!';
|
||||
$lang->custom->notice->confirmDelete = '您确定要删除吗?';
|
||||
$lang->custom->notice->confirmReviewCase = '是否将待评审的用例修改为正常状态?';
|
||||
$lang->custom->notice->storyReviewTip = '按人员、职位、部门勾选后,取所有人员的并集。';
|
||||
$lang->custom->notice->selectAllTip = '勾选所有人员后,会清空并置灰评审人员,同时隐藏职位、部门。';
|
||||
|
||||
$lang->custom->notice->indexPage['product'] = "从8.2版本起增加了产品主页视图,是否默认进入产品主页?";
|
||||
$lang->custom->notice->indexPage['project'] = "从8.2版本起增加了项目主页视图,是否默认进入项目主页?";
|
||||
|
||||
@@ -36,6 +36,18 @@ EOT;
|
||||
<style>
|
||||
.checkbox-primary {width: 170px; margin: 0 10px 10px 0; display: inline-block;}
|
||||
</style>
|
||||
<?php if($module == 'story' and $field == 'review'):?>
|
||||
<style>
|
||||
.reviewBox > th {width: 95px !important;}
|
||||
.reviewBox > td {width: 500px !important;}
|
||||
.checkbox-primary {margin-bottom: 0px; width: 82px !important;}
|
||||
.storyReviewTip {padding-left: 95px;}
|
||||
<?php if($app->getClientLang() != 'zh-cn' and $app->getClientLang() != 'zh-tw'):?>
|
||||
.reviewBox > th {width: 160px !important;}
|
||||
.storyReviewTip {padding-left: 160px;}
|
||||
<?php endif;?>
|
||||
</style>
|
||||
<?php endif;?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='side-col' id='sidebar'>
|
||||
<div class='cell'>
|
||||
@@ -88,18 +100,39 @@ EOT;
|
||||
</tr>
|
||||
</table>
|
||||
<?php elseif(($module == 'story' or $module == 'testcase') and $field == 'review'):?>
|
||||
<table class='table table-form mw-800px'>
|
||||
<tr>
|
||||
<table class='table table-form'>
|
||||
<tr class='reviewBox'>
|
||||
<th class='thWidth'><?php echo $lang->custom->storyReview;?></th>
|
||||
<td><?php echo html::radio('needReview', $lang->custom->reviewList, $needReview);?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr <?php if($needReview and $module == 'testcase') echo "class='hidden'"?>>
|
||||
<?php if($module == 'story'):?>
|
||||
<tr>
|
||||
<?php $space = ($app->getClientLang() != 'zh-cn' and $app->getClientLang() != 'zh-tw') ? ' ': '';?>
|
||||
<td colspan='3'><div class='storyReviewTip'><?php echo sprintf($lang->custom->notice->forceReview, $lang->$module->common) . $lang->custom->notice->storyReviewTip;?></td>
|
||||
</tr>
|
||||
<tr id='userBox'>
|
||||
<th><?php echo $lang->custom->forceReview . $space . $lang->custom->account;?></th>
|
||||
<td><?php echo html::select('forceReview[]', $users, $forceReview, "class='form-control chosen' multiple");?></td>
|
||||
<td>
|
||||
<?php echo html::checkbox('forceReviewAll', array('1' => $lang->custom->allUsers), $forceReviewAll);?>
|
||||
<icon class='icon icon-help' data-toggle='popover' data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->custom->notice->selectAllTip;?>"></icon>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id='roleBox'>
|
||||
<th><?php echo $lang->custom->forceReview . $space . $lang->custom->role;?></th>
|
||||
<td><?php echo html::select('forceReviewRoles[]', $lang->user->roleList, $forceReviewRoles, "class='form-control chosen' multiple");?></td>
|
||||
</tr>
|
||||
<tr id='deptBox'>
|
||||
<th><?php echo $lang->custom->forceReview . $space . $lang->custom->dept;?></th>
|
||||
<td><?php echo html::select('forceReviewDepts[]', $depts, $forceReviewDepts, "class='form-control chosen' multiple");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($module == 'testcase'):?>
|
||||
<tr <?php if($needReview) echo "class='hidden'"?>>
|
||||
<th><?php echo $lang->custom->forceReview;?></th>
|
||||
<td><?php echo html::select('forceReview[]', $users, $forceReview, "class='form-control chosen' multiple");?></td>
|
||||
<td style='width:300px'><?php printf($lang->custom->notice->forceReview, $lang->$module->common);?></td>
|
||||
</tr>
|
||||
<?php if($module == 'testcase'):?>
|
||||
<tr <?php if(!$needReview) echo "class='hidden'"?>>
|
||||
<th><?php echo $lang->custom->forceNotReview;?></th>
|
||||
<td><?php echo html::select('forceNotReview[]', $users, $forceNotReview, "class='form-control chosen' multiple");?></td>
|
||||
@@ -231,6 +264,42 @@ EOT;
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($module == 'story' and $field == 'review'):?>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$('[data-toggle="popover"]').popover();
|
||||
|
||||
toggleBox($("input[name^='forceReviewAll']").prop('checked'));
|
||||
|
||||
$("input[name^='forceReviewAll']").click(function()
|
||||
{
|
||||
toggleBox($(this).prop('checked'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle box.
|
||||
*
|
||||
* @param bool $checked
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function toggleBox(checked)
|
||||
{
|
||||
$('#roleBox').toggleClass('hidden', checked);
|
||||
$('#deptBox').toggleClass('hidden', checked);
|
||||
if(checked)
|
||||
{
|
||||
$('#forceReview').val('').attr('disabled', 'disabled').trigger('chosen:updated');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#forceReview').removeAttr('disabled', 'disabled').trigger('chosen:updated');
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<?php endif;?>
|
||||
<?php if($module == 'testcase' and $field == 'review'):?>
|
||||
<script>
|
||||
$(function()
|
||||
|
||||
@@ -3,4 +3,5 @@ $config->datatable->moduleAlias['product-browse'] = 'story';
|
||||
$config->datatable->moduleAlias['execution-task'] = 'task';
|
||||
$config->datatable->moduleAlias['testtask-cases'] = 'testcase';
|
||||
$config->datatable->moduleAlias['program-project'] = 'project';
|
||||
$config->datatable->moduleAlias['project-bug'] = 'bug';
|
||||
$config->datatable->moduleAlias['execution-bug'] = 'bug';
|
||||
|
||||
@@ -348,7 +348,7 @@ if(!window.kanbanDropRules)
|
||||
'wait': ['wait', 'developing', 'developed', 'canceled'],
|
||||
'developing': ['developing', 'developed', 'pause', 'canceled'],
|
||||
'developed': ['developed', 'developing', 'closed'],
|
||||
'pause': ['pause', 'developing', 'developed', 'canceled'],
|
||||
'pause': ['pause', 'developing', 'canceled'],
|
||||
'canceled': ['canceled', 'developing', 'closed'],
|
||||
'closed': ['closed', 'developing'],
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@ $lang->execution->RDKanban = 'Research & Development Kanban';
|
||||
$lang->execution->allTasks = 'All';
|
||||
$lang->execution->assignedToMe = 'My';
|
||||
$lang->execution->myInvolved = 'Involved';
|
||||
$lang->execution->assignedByMe = 'AssignedByMe';
|
||||
|
||||
$lang->execution->statusSelects[''] = 'More';
|
||||
$lang->execution->statusSelects['wait'] = 'Waiting';
|
||||
@@ -443,6 +444,7 @@ $lang->execution->featureBar['task']['all'] = $lang->execution->allTask
|
||||
$lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed;
|
||||
$lang->execution->featureBar['task']['assignedtome'] = $lang->execution->assignedToMe;
|
||||
$lang->execution->featureBar['task']['myinvolved'] = $lang->execution->myInvolved;
|
||||
$lang->execution->featureBar['task']['assignedbyme'] = $lang->execution->assignedByMe;
|
||||
$lang->execution->featureBar['task']['delayed'] = 'Delayed';
|
||||
$lang->execution->featureBar['task']['needconfirm'] = 'Changed';
|
||||
$lang->execution->featureBar['task']['status'] = $lang->execution->statusSelects[''];
|
||||
|
||||
@@ -260,6 +260,7 @@ $lang->execution->RDKanban = '研发看板';
|
||||
$lang->execution->allTasks = '所有';
|
||||
$lang->execution->assignedToMe = '指派给我';
|
||||
$lang->execution->myInvolved = '由我参与';
|
||||
$lang->execution->assignedByMe = '由我指派';
|
||||
|
||||
$lang->execution->statusSelects[''] = '更多';
|
||||
$lang->execution->statusSelects['wait'] = '未开始';
|
||||
@@ -443,6 +444,7 @@ $lang->execution->featureBar['task']['all'] = $lang->execution->allTask
|
||||
$lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed;
|
||||
$lang->execution->featureBar['task']['assignedtome'] = $lang->execution->assignedToMe;
|
||||
$lang->execution->featureBar['task']['myinvolved'] = $lang->execution->myInvolved;
|
||||
$lang->execution->featureBar['task']['assignedbyme'] = $lang->execution->assignedByMe;
|
||||
$lang->execution->featureBar['task']['delayed'] = '已延期';
|
||||
$lang->execution->featureBar['task']['needconfirm'] = "{$lang->SRCommon}变更";
|
||||
$lang->execution->featureBar['task']['status'] = $lang->execution->statusSelects[''];
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<form class='load-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<?php if($config->systemMode == 'new' and isset($project) and $project->model == 'scrum'):?>
|
||||
<tr>
|
||||
<th class='w-120px'><?php echo $lang->execution->projectName;?></th>
|
||||
<td><?php echo html::select('project', $allProjects, $execution->project, "class='form-control chosen' onchange='changeProject(this.value)' required");?></td><td></td>
|
||||
|
||||
@@ -136,5 +136,3 @@
|
||||
@-moz-document url-prefix(){ .region .kanban-lane-items{scrollbar-width:thin; padding:5px 0px 5px 5px !important;} .region .kanban-card .info .user{right: -6px !important;}}
|
||||
#archivedCards .table-empty-tip {border-style: hidden;}
|
||||
#archivedColumns .table-empty-tip {border-style: hidden;}
|
||||
|
||||
.dragging>.kanban-card{background-color:#fff !important;opacity:.2}
|
||||
|
||||
@@ -2944,7 +2944,7 @@ class kanbanModel extends model
|
||||
$actions .= "<div class='btn-group'>";
|
||||
$actions .= "<a href='javascript:fullScreen();' id='fullScreenBtn' $btnColor class='btn btn-link'><i class='icon icon-fullscreen'></i> {$this->lang->kanban->fullScreen}</a>";
|
||||
|
||||
$CRKanban = !(isset($this->config->CRKanban) and $this->config->CRKanban === '0' and $kanban->status === 'closed');
|
||||
$CRKanban = !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed');
|
||||
$printRegionBtn = ($CRKanban and (common::hasPriv('kanban', 'createRegion') or $printSetHeightBtn or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'import') or common::hasPriv('kanban', 'setColumnWidth')));
|
||||
$printKanbanBtn = (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'));
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ $app->loadLang('productplan');
|
||||
</div>
|
||||
<div class='col-xs-2 card-actions' <?php if($kanban->performable) echo "id='performable'";?>>
|
||||
<?php
|
||||
$CRKanban = ($this->config->CRKanban or $kanban->status != 'closed');
|
||||
$CRKanban = !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed');
|
||||
$canRestore = (commonModel::hasPriv('kanban', 'restoreCard') and $CRKanban);
|
||||
$canDelete = (commonModel::hasPriv('kanban', 'deleteCard') and $CRKanban);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="item-body">
|
||||
<div class="item parent-item hr" data-archived='<?php echo $column->archived;?>' data-id="<?php echo $column->id;?>">
|
||||
<div class="title text-ellipsis"><?php echo $column->name;?></div>
|
||||
<?php if(commonModel::hasPriv('kanban', 'restoreColumn') && $column->archived == '1' && ($this->config->CRKanban or $kanban->status != 'closed')) echo html::a(inlink('restoreColumn', "columnID={$column->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
|
||||
<?php if(commonModel::hasPriv('kanban', 'restoreColumn') && $column->archived == '1' && !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed')) echo html::a(inlink('restoreColumn', "columnID={$column->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
|
||||
</div>
|
||||
<?php if(!empty($column->child) && $column->archived == '0'):?>
|
||||
<?php $count = 1;?>
|
||||
@@ -43,7 +43,7 @@
|
||||
<?php $class = $count == count($column->child) ? 'hr' : '';?>
|
||||
<div class="item child-item <?php echo $class;?>" data-id="<?php echo $childColumn->id;?>" data-archived='<?php echo $childColumn->archived;?>'>
|
||||
<div class="title text-ellipsis"><label class="label label-child"><?php echo $lang->kanban->child;?></label><?php echo $childColumn->name;?></div>
|
||||
<?php if(commonModel::hasPriv('kanban', 'restoreColumn') && $childColumn->archived == '1' && ($this->config->CRKanban or $kanban->status != 'closed')) echo html::a(inlink('restoreColumn', "columnID={$childColumn->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
|
||||
<?php if(commonModel::hasPriv('kanban', 'restoreColumn') && $childColumn->archived == '1' && !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed')) echo html::a(inlink('restoreColumn', "columnID={$childColumn->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
|
||||
</div>
|
||||
<?php $count ++;?>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</div>
|
||||
<div class='main-actions'>
|
||||
<div class="btn-toolbar">
|
||||
<?php if(!$card->deleted and !$card->archived and !($this->config->CRKanban === '0' and $kanban->status === 'closed')):?>
|
||||
<?php if(!$card->deleted and !$card->archived and !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed')):?>
|
||||
<?php
|
||||
//common::printLink('kanban', 'assigntoCard', "cardID=$card->id", "<i class='icon icon-hand-right'></i><span class='text'>{$lang->kanbancard->assign}</span>", '', "class='btn btn-link iframe' title='{$lang->kanbancard->assign}'", true, true);
|
||||
if($kanban->archived)
|
||||
|
||||
@@ -146,9 +146,11 @@ class messageModel extends model
|
||||
if($isonlybody) unset($_GET['onlybody']);
|
||||
|
||||
$moduleName = $objectType == 'case' ? 'testcase' : $objectType;
|
||||
$moduleName = $objectType == 'kanbancard' ? 'kanban' : $objectType;
|
||||
$space = common::checkNotCN() ? ' ' : '';
|
||||
$data = $user->realname . $space . $this->lang->action->label->$actionType . $space . $this->lang->action->objectTypes[$objectType];
|
||||
$data .= ' ' . html::a($sysURL . helper::createLink($moduleName, 'view', "id=$objectID"), "[#{$objectID}::{$object->$field}]");
|
||||
$dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID;
|
||||
$data .= ' ' . html::a($sysURL . helper::createLink($moduleName, 'view', "id=$dataID"), "[#{$objectID}::{$object->$field}]");
|
||||
|
||||
if($isonlybody) $_GET['onlybody'] = 'yes';
|
||||
|
||||
|
||||
+20
-2
@@ -305,6 +305,7 @@ EOF;
|
||||
*/
|
||||
public function story($type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->loadModel('story');
|
||||
/* Save session. */
|
||||
if($this->app->viewType != 'json') $this->session->set('storyList', $this->app->getURI(true), 'my');
|
||||
|
||||
@@ -316,7 +317,15 @@ EOF;
|
||||
/* Append id for secend sort. */
|
||||
$sort = common::appendOrder($orderBy);
|
||||
|
||||
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'story', false);
|
||||
if($type == 'assignedBy')
|
||||
{
|
||||
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'story');
|
||||
}
|
||||
else
|
||||
{
|
||||
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'story', false);
|
||||
}
|
||||
|
||||
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
|
||||
|
||||
/* Assign. */
|
||||
@@ -350,6 +359,7 @@ EOF;
|
||||
public function requirement($type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
/* Save session. */
|
||||
$this->loadModel('story');
|
||||
if($this->app->viewType != 'json') $this->session->set('storyList', $this->app->getURI(true), 'my');
|
||||
|
||||
/* Load pager. */
|
||||
@@ -360,7 +370,15 @@ EOF;
|
||||
/* Append id for secend sort. */
|
||||
$sort = common::appendOrder($orderBy);
|
||||
|
||||
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'requirement');
|
||||
if($type == 'assignedBy')
|
||||
{
|
||||
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'requirement');
|
||||
}
|
||||
else
|
||||
{
|
||||
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'requirement');
|
||||
}
|
||||
|
||||
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
|
||||
|
||||
/* Assign. */
|
||||
|
||||
@@ -74,6 +74,7 @@ $lang->my->storyMenu->reviewByMe = 'ReviewByMe';
|
||||
$lang->my->storyMenu->openedByMe = 'CreatedByMe';
|
||||
$lang->my->storyMenu->reviewedByMe = 'ReviewedByMe';
|
||||
$lang->my->storyMenu->closedByMe = 'ClosedByMe';
|
||||
$lang->my->storyMenu->assignedByMe = 'AssignedByMe';
|
||||
|
||||
$lang->my->projectMenu = new stdclass();
|
||||
$lang->my->projectMenu->doing = 'Doing';
|
||||
|
||||
@@ -74,6 +74,7 @@ $lang->my->storyMenu->reviewByMe = '待我评审';
|
||||
$lang->my->storyMenu->openedByMe = '由我创建';
|
||||
$lang->my->storyMenu->reviewedByMe = '由我评审';
|
||||
$lang->my->storyMenu->closedByMe = '由我关闭';
|
||||
$lang->my->storyMenu->assignedByMe = '由我指派';
|
||||
|
||||
$lang->my->projectMenu = new stdclass();
|
||||
$lang->my->projectMenu->doing = '进行中';
|
||||
|
||||
+17
-4
@@ -324,12 +324,14 @@ class myModel extends model
|
||||
*/
|
||||
public function getAssignedByMe($account, $limit = 0, $pager = null, $orderBy = "id_desc", $projectID = 0, $objectType = '')
|
||||
{
|
||||
$this->loadModel($objectType);
|
||||
$objectList = $this->dao->select('t1.*')
|
||||
->from($this->config->objectTables[$objectType])->alias('t1')
|
||||
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id = t2.objectID and t2.objectType='{$objectType}'")
|
||||
$module = $objectType == 'requirement' ? 'story' : $objectType;
|
||||
$this->loadModel($module);
|
||||
$objectList = $this->dao->select('DISTINCT t1.*')
|
||||
->from($this->config->objectTables[$module])->alias('t1')
|
||||
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id = t2.objectID and t2.objectType='{$module}'")
|
||||
->where('t2.actor')->eq($account)
|
||||
->andWhere('t2.action')->eq('assigned')
|
||||
->beginIF($objectType == 'requirement' or $objectType == 'story')->andWhere('t1.type')->eq($objectType)->fi()
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy($orderBy)
|
||||
->page($pager, 't1.id')
|
||||
@@ -358,7 +360,18 @@ class myModel extends model
|
||||
$productPairs = $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('id')->in($productList)->fetchPairs('id');
|
||||
foreach($objectList as $bug) $bug->productName = zget($productPairs, $bug->product);
|
||||
}
|
||||
if($objectType == 'requirement' or $objectType == 'story')
|
||||
{
|
||||
$productList = array();
|
||||
foreach($objectList as $story) $productList[$story->product] = $story->product;
|
||||
$productPairs = $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('id')->in($productList)->fetchPairs('id');
|
||||
foreach($objectList as $story) $story->productTitle = zget($productPairs, $story->product);
|
||||
|
||||
$planList = array();
|
||||
foreach($objectList as $story) $planList[$story->plan] = $story->plan;
|
||||
$planPairs = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)->where('id')->in($planList)->fetchPairs('id');
|
||||
foreach($objectList as $story) $story->planTitle = zget($planPairs, $story->plan);
|
||||
}
|
||||
return $objectList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
$recTotalLabel = " <span class='label label-light label-badge'>{$pager->recTotal}</span>";
|
||||
if($app->rawMethod == 'contribute')
|
||||
{
|
||||
echo html::a(inlink($app->rawMethod, "mode=requirement&type=openedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->openedByMe}</span>" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink($app->rawMethod, "mode=requirement&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=requirement&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' : '') . "'");
|
||||
echo html::a(inlink($app->rawMethod, "mode=requirement&type=openedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->openedByMe}</span>" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink($app->rawMethod, "mode=requirement&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=requirement&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' : '') . "'");
|
||||
echo html::a(inlink($app->rawMethod, "mode=requirement&type=assignedBy&&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->assignedByMe}</span>" . ($type == 'assignedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedBy' ? ' btn-active-text' : '') . "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
echo html::a(inlink($app->rawMethod, "mode=story&type=openedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->openedByMe}</span>" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
|
||||
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' : '') . "'");
|
||||
echo html::a(inlink($app->rawMethod, "mode=story&type=assignedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->assignedByMe}</span>" . ($type == 'assignedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedBy' ? ' btn-active-text' : '') . "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
$config->product = new stdclass();
|
||||
$config->product->orderBy = 'isClosed,order_desc';
|
||||
$config->product->orderBy = 'isClosed,program_asc,order_asc';
|
||||
|
||||
$config->product->customBatchEditFields = 'line,PO,QD,RD,status,type,acl';
|
||||
if($config->systemMode == 'new') $config->product->customBatchEditFields = 'program,' . $config->product->customBatchEditFields;
|
||||
|
||||
@@ -1197,7 +1197,7 @@ class product extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function all($browseType = 'noclosed', $orderBy = 'program_asc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
public function all($browseType = 'noclosed', $orderBy = 'program_asc,order_asc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
/* Load module and set session. */
|
||||
$this->loadModel('program');
|
||||
|
||||
@@ -13,7 +13,9 @@ $(function()
|
||||
/* Set movable conditions. */
|
||||
canMoveHere: function($ele, $target)
|
||||
{
|
||||
return $ele.data('parent') === $target.data('parent');
|
||||
var canMove = true;
|
||||
if($ele.hasClass('no-nest')) canMove = $target.hasClass('no-nest') ? true : false;
|
||||
return $ele.data('parent') === $target.data('parent') && canMove;
|
||||
},
|
||||
start: function(e)
|
||||
{
|
||||
|
||||
@@ -143,6 +143,7 @@ $lang->product->closedStory = 'Closed';
|
||||
$lang->product->unclosed = 'Open';
|
||||
$lang->product->unplan = 'Unplanned';
|
||||
$lang->product->viewByUser = 'By User';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = 'Products Ownedbyme';
|
||||
@@ -213,6 +214,7 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
|
||||
@@ -143,6 +143,7 @@ $lang->product->closedStory = '已关闭';
|
||||
$lang->product->unclosed = '未关闭';
|
||||
$lang->product->unplan = "未计划";
|
||||
$lang->product->viewByUser = '按用户查看';
|
||||
$lang->product->assignedByMe = '我指派';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = '我负责的' . $lang->productCommon;
|
||||
@@ -213,6 +214,7 @@ $lang->product->featureBar['all']['all'] = '所有' . $lang->productCommon;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
|
||||
@@ -989,6 +989,7 @@ class productModel extends model
|
||||
if($browseType == 'changedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'changed', $type, $sort, $pager);
|
||||
if($browseType == 'willclose') $stories = $this->story->get2BeClosed($productID, $branch, $modules, $type, $sort, $pager);
|
||||
if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'closed', $type, $sort, $pager);
|
||||
if($browseType == 'assignedbyme') $stories = $this->story->getByAssignedBy($productID, $branch, $modules, $this->app->user->account, $type, $sort, $pager);
|
||||
|
||||
return $stories;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<?php if($product->type != 'normal'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
<td><?php echo html::select('branch', $branches, $defaultBranch, "class='form-control chosen'");?></td><td></td><td></td>
|
||||
<td><?php echo html::select('branch', $branches, $branch, "class='form-control chosen'");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -80,7 +80,7 @@ $lang->program->exRateNotNegative = 'The『exchange rate』should not be n
|
||||
$lang->program->changePRJUnit = 'Update the budget unit of the project';
|
||||
|
||||
$lang->program->progress = 'Progress';
|
||||
$lang->program->children = 'Child';
|
||||
$lang->program->children = 'Add Child';
|
||||
$lang->program->allInvest = 'Input';
|
||||
$lang->program->teamCount = 'Team';
|
||||
$lang->program->longTime = 'Long-Term';
|
||||
|
||||
@@ -80,7 +80,7 @@ $lang->program->exRateNotNegative = '『汇率』不能是负数。';
|
||||
$lang->program->changePRJUnit = '更新项目预算单位';
|
||||
|
||||
$lang->program->progress = '项目进度';
|
||||
$lang->program->children = '子项目集';
|
||||
$lang->program->children = '添加子项目集';
|
||||
$lang->program->allInvest = '项目集总投入';
|
||||
$lang->program->teamCount = '总人数';
|
||||
$lang->program->longTime = '长期';
|
||||
|
||||
@@ -44,13 +44,17 @@
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->program->create;?></h2>
|
||||
<h2><?php echo isset($parentProgram->id) ? $lang->program->children : $lang->program->create;?></h2>
|
||||
</div>
|
||||
<form class='form-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->program->parent;?></th>
|
||||
<td><?php echo html::select('parent', $parents, isset($parentProgram->id) ? $parentProgram->id : 0, "class='form-control chosen' onchange=setBudgetTipsAndAclList(this.value)");?>
|
||||
<td>
|
||||
<?php $disabled = isset($parentProgram->id) ? 'disabled' : '';?>
|
||||
<?php echo html::select('parent', $parents, isset($parentProgram->id) ? $parentProgram->id : 0, "class='form-control chosen' onchange=setBudgetTipsAndAclList(this.value) $disabled");?>
|
||||
<?php if($disabled) echo html::hidden('parent', $parentProgram->id);?>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
+61
-16
@@ -971,11 +971,13 @@ class project extends control
|
||||
$this->loadModel('bug');
|
||||
$this->loadModel('user');
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('datatable');
|
||||
|
||||
/* Save session. */
|
||||
$this->session->set('bugList', $this->app->getURI(true), 'project');
|
||||
$this->project->setMenu($projectID);
|
||||
|
||||
$product = $this->product->getById($productID);
|
||||
$project = $this->project->getByID($projectID);
|
||||
$type = strtolower($type);
|
||||
$queryID = ($type == 'bysearch') ? (int)$param : 0;
|
||||
@@ -983,7 +985,7 @@ class project extends control
|
||||
$branchID = isset($products[$productID]) ? current($products[$productID]->branches) : 0;
|
||||
|
||||
$productPairs = array('0' => $this->lang->product->all);
|
||||
foreach($products as $product) $productPairs[$product->id] = $product->name;
|
||||
foreach($products as $productData) $productPairs[$productData->id] = $productData->name;
|
||||
$this->lang->modulePageNav = $this->product->select($productPairs, $productID, 'project', 'bug', '', $branchID, 0, '', false);
|
||||
|
||||
/* Header and position. */
|
||||
@@ -991,6 +993,8 @@ class project extends control
|
||||
$position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name);
|
||||
$position[] = $this->lang->bug->common;
|
||||
|
||||
$executions = $this->loadModel('execution')->getPairs($projectID, 'all', 'empty|withdelete');
|
||||
|
||||
/* Load pager and get bugs, user. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
@@ -1008,22 +1012,63 @@ class project extends control
|
||||
$actionURL = $this->createLink('project', 'bug', "projectID=$projectID&productID=$productID&orderBy=$orderBy&build=$build&type=bysearch&queryID=myQueryID");
|
||||
$this->loadModel('execution')->buildBugSearchForm($products, $queryID, $actionURL, 'project');
|
||||
|
||||
$showBranch = false;
|
||||
$branchOption = array();
|
||||
$branchTagOption = array();
|
||||
if($product and $product->type != 'normal')
|
||||
{
|
||||
/* Display of branch label. */
|
||||
$showBranch = $this->loadModel('branch')->showBranch($productID);
|
||||
|
||||
/* Display status of branch. */
|
||||
$branches = $this->loadModel('branch')->getList($productID, 0, 'all');
|
||||
foreach($branches as $branchInfo)
|
||||
{
|
||||
$branchOption[$branchInfo->id] = $branchInfo->name;
|
||||
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
|
||||
}
|
||||
}
|
||||
|
||||
$showModule = !empty($this->config->datatable->bugBrowse->showModule) ? $this->config->datatable->bugBrowse->showModule : '';
|
||||
|
||||
$storyIdList = $taskIdList = array();
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
if($bug->story) $storyIdList[$bug->story] = $bug->story;
|
||||
if($bug->task) $taskIdList[$bug->task] = $bug->task;
|
||||
if($bug->toTask) $taskIdList[$bug->toTask] = $bug->toTask;
|
||||
}
|
||||
$storyList = $storyIdList ? $this->loadModel('story')->getByList($storyIdList) : array();
|
||||
$taskList = $taskIdList ? $this->loadModel('task')->getByList($taskIdList) : array();
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tabID = 'bug';
|
||||
$this->view->build = $this->loadModel('build')->getById($build);
|
||||
$this->view->buildID = $this->view->build ? $this->view->build->id : 0;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->users = $users;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->project = $this->project->getById($projectID);
|
||||
$this->view->branchID = empty($this->view->build->branch) ? $branchID : $this->view->build->branch;
|
||||
$this->view->memberPairs = $memberPairs;
|
||||
$this->view->type = $type;
|
||||
$this->view->param = $param;
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tabID = 'bug';
|
||||
$this->view->build = $this->loadModel('build')->getById($build);
|
||||
$this->view->buildID = $this->view->build ? $this->view->build->id : 0;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->users = $users;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->project = $this->project->getById($projectID);
|
||||
$this->view->branchID = empty($this->view->build->branch) ? $branchID : $this->view->build->branch;
|
||||
$this->view->memberPairs = $memberPairs;
|
||||
$this->view->type = $type;
|
||||
$this->view->param = $param;
|
||||
$this->view->builds = $this->loadModel('build')->getBuildPairs($productID);
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->memberPairs = $this->user->getPairs('noletter|noclosed');
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->modulePairs = $showModule ? $this->loadModel('tree')->getModulePairs($productID, 'bug', $showModule) : array();
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID);
|
||||
$this->view->stories = $storyList;
|
||||
$this->view->tasks = $taskList;
|
||||
$this->view->projectPairs = $this->project->getPairsByProgram();
|
||||
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/datatable.fix.html.php';?>
|
||||
<style>
|
||||
#subHeader #dropMenu .col-left .list-group {margin-bottom: 0px; padding-top: 10px;}
|
||||
#subHeader #dropMenu .col-left {padding-bottom: 0px;}
|
||||
@@ -41,86 +42,54 @@
|
||||
</p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<form class='main-table' method='post' id='projectBugForm' data-ride="table">
|
||||
<table class='table has-sort-head' id='bugList'>
|
||||
<?php $canBatchAssignTo = common::hasPriv('bug', 'batchAssignTo');?>
|
||||
<?php $vars = "projectID={$project->id}&productID=$productID&orderBy=%s&build=$buildID&type=$type¶m=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
|
||||
<?php
|
||||
$datatableId = $this->moduleName . ucfirst($this->methodName);
|
||||
$useDatatable = (isset($config->datatable->$datatableId->mode) and $config->datatable->$datatableId->mode == 'datatable');
|
||||
?>
|
||||
<form class='main-table' method='post' id='projectBugForm' <?php if(!$useDatatable) echo "data-ride='table'";?>>
|
||||
<div class="table-header fixed-right">
|
||||
<nav class="btn-toolbar pull-right setting"></nav>
|
||||
</div>
|
||||
<?php
|
||||
$vars = "projectID={$project->id}&productID=$productID&orderBy=%s&build=$buildID&type=$type¶m=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";
|
||||
if($useDatatable) include '../../common/view/datatable.html.php';
|
||||
else include '../../common/view/tablesorter.html.php';
|
||||
|
||||
$setting = $this->datatable->getSetting('project');
|
||||
$widths = $this->datatable->setFixedFieldWidth($setting);
|
||||
$columns = 0;
|
||||
|
||||
$canBatchAssignTo = common::hasPriv('bug', 'batchAssignTo');
|
||||
?>
|
||||
<?php if(!$useDatatable) echo '<div class="table-responsive">';?>
|
||||
<table class='table has-sort-head<?php if($useDatatable) echo ' datatable';?>' id='bugList' data-fixed-left-width='<?php echo $widths['leftWidth']?>' data-fixed-right-width='<?php echo $widths['rightWidth']?>'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='c-id'>
|
||||
<?php if($canBatchAssignTo):?>
|
||||
<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 class='c-severity' title=<?php echo $lang->bug->severity;?>><?php common::printOrderLink('severity', $orderBy, $vars, $lang->bug->severityAB);?></th>
|
||||
<th class='c-pri' title=<?php echo $lang->project->pri;?>><?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<th><?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='c-user'><?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='c-user'><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->assignedToAB);?></th>
|
||||
<th class='c-user'><?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedBy);?></th>
|
||||
<th class='c-resolution'><?php common::printOrderLink('resolution', $orderBy, $vars, $lang->bug->resolutionAB);?></th>
|
||||
<th class='c-actions-5'><?php echo $lang->actions;?></th>
|
||||
<?php
|
||||
foreach($setting as $key => $value)
|
||||
{
|
||||
if($value->show)
|
||||
{
|
||||
$this->datatable->printHead($value, $orderBy, $vars, $canBatchAssignTo);
|
||||
$columns ++;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php
|
||||
$hasCustomSeverity = false;
|
||||
foreach($lang->bug->severityList as $severityKey => $severityValue)
|
||||
{
|
||||
if(!empty($severityKey) and (string)$severityKey != (string)$severityValue)
|
||||
{
|
||||
$hasCustomSeverity = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tbody>
|
||||
<?php foreach($bugs as $bug):?>
|
||||
<?php
|
||||
$canBeChanged = common::canBeChanged('bug', $bug);
|
||||
$arrtibute = $canBeChanged ? '' : 'disabled';
|
||||
$viewLink = helper::createLink('bug', 'view', "bugID=$bug->id");
|
||||
?>
|
||||
<tr>
|
||||
<td class='cell-id'>
|
||||
<?php if($canBatchAssignTo):?>
|
||||
<?php echo html::checkbox('bugIDList', array($bug->id => ''), '', $arrtibute) . html::a($viewLink, sprintf('%03d', $bug->id), '', "data-app={$this->app->tab}");?>
|
||||
<?php else:?>
|
||||
<?php printf('%03d', $bug->id);?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if($hasCustomSeverity):?>
|
||||
<span class='<?php echo 'label-severity-custom';?>' title='<?php echo zget($lang->bug->severityList, $bug->severity);?>' data-severity='<?php echo $bug->severity;?>'><?php echo zget($lang->bug->severityList, $bug->severity, $bug->severity);?></span>
|
||||
<?php else:?>
|
||||
<span class='<?php echo 'label-severity';?>' title='<?php echo zget($lang->bug->severityList, $bug->severity);?>' data-severity='<?php echo $bug->severity;?>'></span>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td><span class='label-pri <?php echo 'label-pri-' . $bug->pri?>' title='<?php echo zget($lang->bug->priList, $bug->pri, $bug->pri)?>'><?php echo zget($lang->bug->priList, $bug->pri, $bug->pri)?></span></td>
|
||||
<td class='text-left c-name' title="<?php echo $bug->title?>"><?php echo html::a($viewLink, $bug->title, null, "style='color: $bug->color' data-app={$this->app->tab}");?></td>
|
||||
<td><?php echo zget($users, $bug->openedBy, $bug->openedBy);?></td>
|
||||
<td class='c-assignedTo has-btn text-left'><?php $this->bug->printAssignedHtml($bug, $users);?></td>
|
||||
<td><?php echo zget($users, $bug->resolvedBy, $bug->resolvedBy);?></td>
|
||||
<td><?php echo zget($lang->bug->resolutionList, $bug->resolution);?></td>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
if($canBeChanged)
|
||||
{
|
||||
$params = "bugID=$bug->id";
|
||||
common::printIcon('bug', 'confirmBug', $params, $bug, 'list', 'ok', '', 'iframe', true);
|
||||
common::printIcon('bug', 'resolve', $params, $bug, 'list', 'checked', '', 'iframe', true);
|
||||
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params,projectID={$bug->project}", $bug, 'list', 'copy');
|
||||
common::printIcon('bug', 'edit', $params, $bug, 'list');
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<tr data-id='<?php echo $bug->id?>'>
|
||||
<?php foreach($setting as $value) $this->bug->printCell($value, $bug, $users, $builds, $branchOption, $modulePairs, $executions, $plans, $stories, $tasks, $useDatatable ? 'datatable' : 'table', $projectPairs);?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if(!$useDatatable) echo '</div>';?>
|
||||
<div class='table-footer'>
|
||||
<?php if($canBatchAssignTo):?>
|
||||
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
|
||||
@@ -166,4 +135,9 @@
|
||||
</div>
|
||||
<?php js::set('replaceID', 'bugList');?>
|
||||
<?php js::set('browseType', $type);?>
|
||||
<script>
|
||||
<?php if(!empty($useDatatable)):?>
|
||||
$(function(){$('#projectBugForm').table();})
|
||||
<?php endif;?>
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
+68
-11
@@ -2437,6 +2437,7 @@ class storyModel extends model
|
||||
* Get stories by assignedTo.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param string $account
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
@@ -2453,6 +2454,8 @@ class storyModel extends model
|
||||
* Get stories by openedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $account
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
@@ -2469,6 +2472,8 @@ class storyModel extends model
|
||||
* Get stories by reviewedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $account
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
@@ -2503,6 +2508,8 @@ class storyModel extends model
|
||||
* Get stories by closedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $account
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
@@ -2518,6 +2525,8 @@ class storyModel extends model
|
||||
* Get stories by status.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $status
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
@@ -2533,14 +2542,15 @@ class storyModel extends model
|
||||
/**
|
||||
* Get stories by plan.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param array $modules
|
||||
* @param int $plan
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param array $modules
|
||||
* @param int $plan
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByPlan($productID, $branch, $modules, $plan, $type = 'story', $orderBy = '', $pager = null)
|
||||
@@ -2548,6 +2558,24 @@ class storyModel extends model
|
||||
return $this->getByField($productID, $branch, $modules, 'plan', $plan, $type, $orderBy, $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stories by assignedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $account
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByAssignedBy($productID, $branch, $modules, $account, $type = 'story', $orderBy = '', $pager = null)
|
||||
{
|
||||
return $this->getByField($productID, $branch, $modules, 'assignedBy', $account, $type, $orderBy, $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stories by a field.
|
||||
*
|
||||
@@ -2565,7 +2593,10 @@ class storyModel extends model
|
||||
*/
|
||||
public function getByField($productID, $branch, $modules, $fieldName, $fieldValue, $type = 'story', $orderBy = '', $pager = null, $operator = 'equal')
|
||||
{
|
||||
if(!$this->loadModel('common')->checkField(TABLE_STORY, $fieldName) and $fieldName != 'reviewBy') return array();
|
||||
if(!$this->loadModel('common')->checkField(TABLE_STORY, $fieldName) and $fieldName != 'reviewBy' and $fieldName != 'assignedBy') return array();
|
||||
|
||||
$actionIDList = array();
|
||||
if($fieldName == 'assignedBy') $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('story')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($fieldValue)->fetchPairs('objectID', 'objectID');
|
||||
|
||||
$sql = $this->dao->select('t1.*')->from(TABLE_STORY)->alias('t1');
|
||||
if($fieldName == 'reviewBy') $sql = $sql->leftJoin(TABLE_STORYREVIEW)->alias('t2')->on('t1.id = t2.story and t1.version = t2.version');
|
||||
@@ -2575,13 +2606,14 @@ class storyModel extends model
|
||||
->andWhere('t1.type')->eq($type)
|
||||
->beginIF($branch != 'all')->andWhere("t1.branch")->eq($branch)->fi()
|
||||
->beginIF($modules)->andWhere("t1.module")->in($modules)->fi()
|
||||
->beginIF($operator == 'equal' and $fieldName != 'reviewBy')->andWhere('t1.' . $fieldName)->eq($fieldValue)->fi()
|
||||
->beginIF($operator == 'include' and $fieldName != 'reviewBy')->andWhere('t1.' . $fieldName)->like("%$fieldValue%")->fi()
|
||||
->beginIF($operator == 'equal' and $fieldName != 'reviewBy' and $fieldName != 'assignedBy')->andWhere('t1.' . $fieldName)->eq($fieldValue)->fi()
|
||||
->beginIF($operator == 'include' and $fieldName != 'reviewBy' and $fieldName != 'assignedBy')->andWhere('t1.' . $fieldName)->like("%$fieldValue%")->fi()
|
||||
->beginIF($fieldName == 'reviewBy')
|
||||
->andWhere('t2.reviewer')->eq($this->app->user->account)
|
||||
->andWhere('t2.result')->eq('')
|
||||
->andWhere('t1.status')->in('draft,changed')
|
||||
->fi()
|
||||
->beginIF($fieldName == 'assignedBy')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
@@ -2592,6 +2624,8 @@ class storyModel extends model
|
||||
* Get to be closed stories.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $modules
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
@@ -4319,7 +4353,30 @@ class storyModel extends model
|
||||
public function checkForceReview()
|
||||
{
|
||||
$forceReview = false;
|
||||
if(!empty($this->config->story->forceReview)) $forceReview = strpos(",{$this->config->story->forceReview},", ",{$this->app->user->account},") !== false;
|
||||
|
||||
if(isset($this->config->story->forceReviewAll) and $this->config->story->forceReviewAll) return true;
|
||||
|
||||
$forceUsers = '';
|
||||
if(!empty($this->config->story->forceReview)) $forceUsers = $this->config->story->forceReview;
|
||||
|
||||
if(!empty($this->config->story->forceReviewRoles) or !empty($this->config->story->forceReviewDepts))
|
||||
{
|
||||
$users = $this->dao->select('account')->from(TABLE_USER)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere(true, true)
|
||||
->beginIF(!empty($this->config->story->forceReviewRoles))
|
||||
->andWhere('role', true)->in($this->config->story->forceReviewRoles)
|
||||
->andWhere('role')->ne('')
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->beginIF(!empty($this->config->story->forceReviewDepts))->orWhere('dept')->in($this->config->story->forceReviewDepts)->fi()
|
||||
->markRight(1)
|
||||
->fetchAll('account');
|
||||
|
||||
$forceUsers .= "," . implode(',', array_keys($users));
|
||||
}
|
||||
|
||||
$forceReview = strpos(",{$forceUsers},", ",{$this->app->user->account},") !== false;
|
||||
|
||||
return $forceReview;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,15 @@ $(function()
|
||||
{
|
||||
if($(this).val() !== '') left = $(this).val();
|
||||
});
|
||||
if(left === '0') return confirm(confirmRecord);
|
||||
if(left == '0')
|
||||
{
|
||||
var confirmMsg = confirm(confirmRecord);
|
||||
if(confirmMsg == false)
|
||||
{
|
||||
$('#submit').attr("disabled", false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#recordForm .showinonlybody').each(function()
|
||||
|
||||
@@ -2186,6 +2186,10 @@ class taskModel extends model
|
||||
if(is_string($type)) $type = strtolower($type);
|
||||
$fields = 'DISTINCT t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName';
|
||||
$this->config->edition == 'max' && $fields .= ', t6.name as designName, t6.version as latestDesignVersion';
|
||||
|
||||
$actionIDList = array();
|
||||
if($type == 'assignedbyme') $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('task')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($this->app->user->account)->fetchPairs('objectID', 'objectID');
|
||||
|
||||
$tasks = $this->dao->select($fields)
|
||||
->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
|
||||
@@ -2207,8 +2211,9 @@ class taskModel extends model
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->beginIF($type == 'delayed')->andWhere('t1.deadline')->gt('1970-1-1')->andWhere('t1.deadline')->lt(date(DT_DATE1))->andWhere('t1.status')->in('wait,doing')->fi()
|
||||
->beginIF(is_array($type) or strpos(',all,undone,needconfirm,assignedtome,delayed,finishedbyme,myinvolved,', ",$type,") === false)->andWhere('t1.status')->in($type)->fi()
|
||||
->beginIF(is_array($type) or strpos(',all,undone,needconfirm,assignedtome,delayed,finishedbyme,myinvolved,assignedbyme,', ",$type,") === false)->andWhere('t1.status')->in($type)->fi()
|
||||
->beginIF($modules)->andWhere('t1.module')->in($modules)->fi()
|
||||
->beginIF($type == 'assignedbyme')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi()
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy($orderBy)
|
||||
->page($pager, 't1.id')
|
||||
|
||||
@@ -2769,6 +2769,53 @@ class userModel extends model
|
||||
return $visionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users who have authority to create stories.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCanCreateStoryUsers()
|
||||
{
|
||||
$users = $this->getPairs('noclosed|nodeleted');
|
||||
$groupList = $this->dao->select('*')->from(TABLE_USERGROUP)
|
||||
->where('account')->in(array_keys($users))
|
||||
->fetchGroup('account', 'group');
|
||||
|
||||
$hasPrivGroups = $this->dao->select('*')->from(TABLE_GROUPPRIV)
|
||||
->where('module')->eq('story')
|
||||
->andWhere('(method')->eq('create')
|
||||
->orWhere('method')->eq('batchCreate')
|
||||
->markRight(1)
|
||||
->fetchAll('group');
|
||||
|
||||
foreach($users as $account => $user)
|
||||
{
|
||||
if(empty($user) or strpos($this->app->company->admins, ",{$account},") !== false) continue;
|
||||
|
||||
if(!isset($groupList[$account]))
|
||||
{
|
||||
unset($users[$account]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$groups = $groupList[$account];
|
||||
$hasPriv = false;
|
||||
foreach($groups as $groupID => $group)
|
||||
{
|
||||
if(isset($hasPrivGroups[$groupID]))
|
||||
{
|
||||
$hasPriv = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$hasPriv) unset($users[$account]);
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch admin of ZenTao.
|
||||
*
|
||||
|
||||
@@ -417,7 +417,7 @@ class webhookModel extends model
|
||||
$object = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
|
||||
$field = $this->config->action->objectNameFields[$objectType];
|
||||
$host = empty($webhook->domain) ? common::getSysURL() : $webhook->domain;
|
||||
$viewLink = $this->getViewLink($objectType, $objectID);
|
||||
$viewLink = $this->getViewLink($objectType == 'kanbancard' ? 'kanban' : $objectType, $objectType == 'kanbancard' ? $object->kanban : $objectID);
|
||||
$objectTypeName = ($objectType == 'story' and $object->type == 'requirement') ? $this->lang->action->objectTypes['requirement'] : $this->lang->action->objectTypes[$objectType];
|
||||
$title = $this->app->user->realname . $this->lang->action->label->$actionType . $objectTypeName;
|
||||
$text = $title . ' ' . "[#{$objectID}::{$object->$field}](" . $host . $viewLink . ")";
|
||||
|
||||
@@ -16,7 +16,7 @@ class Project
|
||||
}
|
||||
|
||||
/**
|
||||
* Test start a project.
|
||||
* Test start a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
@@ -35,8 +35,8 @@ class Project
|
||||
|
||||
/**
|
||||
* Test create project.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @param array $params
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -88,4 +88,19 @@ class Project
|
||||
|
||||
return $this->project->getByIdList($data['projectIdList']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get all the projects under the program set to which an project belongs
|
||||
*
|
||||
* @param object $project
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getBrotherProjectsTest($project)
|
||||
{
|
||||
$projectIds = $this->project->getBrotherProjects($project);
|
||||
|
||||
if(dao::isError()) return array('message' => dao::getError());
|
||||
return $projectIds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ cid=1
|
||||
pid=1
|
||||
|
||||
更新id为10的项目集信息 >> 测试更新项目集十
|
||||
更新项目集名称为空时 >> 『项目集名称』不能为空。
|
||||
当计划开始为空时更新项目集信息 >> 『计划开始』不能为空。
|
||||
当计划完成为空时更新项目集信息 >> 『计划完成』不能为空。
|
||||
当计划完成小于计划开始时 >> 『计划完成』应当大于『2020-10-10』。
|
||||
项目集名称已经存在时 >> 『项目集名称』已经有『项目集1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。
|
||||
项目集开始时间小于父项目集时 >> 父项目集的开始日期:2019-09-09,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2019-09-09,完成日期不能大于父项目集的完成日期
|
||||
父项目集的开始日期大于子项目集的开始日期时 >> 子项目集的最小开始日期:2022-03-26,父项目集的开始日期不能大于子项目集的最小开始日期
|
||||
项目集开始时间小于父项目集时 >> 父项目集的开始日期:2022-03-26,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-06-02,完成日期不能大于父项目集的完成日期
|
||||
更新未开始的项目集实际开始时间 >> doing
|
||||
|
||||
*/
|
||||
|
||||
@@ -25,7 +26,7 @@ $data = array(
|
||||
'parent' => '0',
|
||||
'name' => '测试更新项目集十',
|
||||
'begin' => '2020-10-10',
|
||||
'end' => '2022-06-03',
|
||||
'end' => '2022-09-03',
|
||||
'acl' => 'private',
|
||||
'budget' => '100',
|
||||
'budgetUnit' => 'CNY',
|
||||
@@ -52,10 +53,14 @@ $beginLtParentProgram = $data;
|
||||
$beginLtParentProgram['parent'] = '9';
|
||||
$beginLtParentProgram['begin'] = '2019-01-01';
|
||||
|
||||
$realBeganProgram = $data;
|
||||
$realBeganProgram['realBegan'] = '2020-11-10';
|
||||
|
||||
r($program->update(10, $normalProgram)) && p('name') && e('测试更新项目集十'); // 正常更新项目集的情况
|
||||
r($program->update(10, $emptyTitleProgram)) && p('message[name]:0') && e('『项目集名称』不能为空。'); // 更新项目集名称为空时
|
||||
r($program->update(10, $emptyBeginProgram)) && p('message[begin]:0') && e('『计划开始』不能为空。'); // 当计划完成为空时更新项目集信息
|
||||
r($program->update(10, $emptyEndProgram)) && p('message:end') && e('子项目的最大完成日期:2022-05-27,父项目的完成日期不能小于子项目的最大完成日期'); //当计划完成小于计划开始时
|
||||
r($program->update(10, $emptyBeginProgram)) && p('message[begin]:0') && e('『计划开始』不能为空。'); // 当计划开始为空时更新项目集信息
|
||||
r($program->update(10, $emptyEndProgram)) && p('message:end') && e('『计划完成』不能为空。'); // 当计划完成为空时更新项目集信息
|
||||
r($program->update(10, $beginGtEndProgram)) && p('message:begin') && e('子项目集的最小开始日期:2022-02-01,父项目集的开始日期不能大于子项目集的最小开始日期'); // 父项目集的开始日期大于子项目集的开始日期时
|
||||
r($program->update(10, $beginLtParentProgram)) && p('message:begin;message:end') && e('父项目集的开始日期:2022-02-09,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-04-16,完成日期不能大于父项目集的完成日期'); // 项目集开始、结束日期和子项目不符的情况
|
||||
r($program->update(10, $beginLtParentProgram)) && p('message:begin;message:end') && e('父项目集的开始日期:2022-03-26,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-06-02,完成日期不能大于父项目集的完成日期'); // 项目集开始、结束日期和子项目不符的情况
|
||||
r($program->update(10, $realBeganProgram)) && p('status') && e('doing'); // 更新未开始的项目集实际开始时间
|
||||
system("./ztest init");
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/project.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->getBrotherProjects();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取项目id为11同一个项目集下的所有项目个数 >> 9
|
||||
获取id为731的顶级项目兄弟项目个数 >> 1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->app->loadConfig('execution');
|
||||
$project = new Project();
|
||||
|
||||
$projectInst = $project->project->getById(11);
|
||||
$programProjects = $project->getBrotherProjectsTest($projectInst);
|
||||
$projectInst = $project->project->getById(731);
|
||||
$depProjects = $project->getBrotherProjectsTest($projectInst);
|
||||
|
||||
r(count($programProjects)) && p() && e('9'); // 获取项目id为11同一个项目集下的所有项目个数
|
||||
r(count($depProjects)) && p() && e('1'); // 获取id为731的顶级项目兄弟项目个数
|
||||
@@ -91,8 +91,6 @@
|
||||
|
||||
if(config.debug > 2)
|
||||
{
|
||||
console.log(document.title || location.href, 'tid', _tid);
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#tid').prepend('<code class="bg-blue">localtid=' + _tid + '</code>');
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
@@ -48,12 +48,13 @@ class xuanxuanMessage extends messageModel
|
||||
$server = $this->loadModel('im')->getServer('zentao');
|
||||
$onlybody = isset($_GET['onlybody']) ? $_GET['onlybody'] : '';
|
||||
unset($_GET['onlybody']);
|
||||
$url = $server . helper::createLink($objectType, 'view', "id=$objectID", 'html');
|
||||
$dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID;
|
||||
$url = $server . helper::createLink($objectType == 'kanbancard' ? 'kanban' : $objectType, 'view', "id=$dataID", 'html');
|
||||
|
||||
$target = '';
|
||||
if(!empty($object->assignedTo)) $target .= $object->assignedTo;
|
||||
if(!empty($object->mailto)) $target .= ",{$object->mailto}";
|
||||
if($objectType == 'mr' && !empty($object->createdBy)) $target .= ",{$object->createdBy}";
|
||||
if(($objectType == 'mr' or $objectType == 'kanbancard') and !empty($object->createdBy)) $target .= ",{$object->createdBy}";
|
||||
$target = trim($target, ',');
|
||||
$target = $this->dao->select('id')->from(TABLE_USER)
|
||||
->where('account')->in($target)
|
||||
|
||||
Reference in New Issue
Block a user