Merge branch '180'

This commit is contained in:
孙广明
2022-01-04 22:41:23 +08:00
84 changed files with 627 additions and 253 deletions
+1 -1
View File
@@ -296,5 +296,5 @@ $config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme');
/* Program privs.*/
$config->programPriv = new stdclass();
$config->programPriv->scrum = array('projectstory', 'projectrelease', 'project', 'build', 'bug', 'testcase', 'testreport', 'caselib', 'doc', 'repo', 'meeting', 'stakeholder');
$config->programPriv->scrum = array('projectstory', 'projectrelease', 'project', 'build', 'bug', 'testcase', 'testreport', 'doc', 'repo', 'meeting', 'stakeholder', 'testtask');
$config->programPriv->waterfall = array_merge($config->programPriv->scrum, array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'issue', 'risk', 'opportunity', 'measrecord', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport'));
+1 -1
View File
@@ -55,4 +55,4 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,';
+1 -1
View File
@@ -60,7 +60,7 @@ class action extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$trashes = $this->action->getTrashes($type, $sort, $pager);
/* Title and position. */
+1
View File
@@ -53,6 +53,7 @@ $lang->action->confirmHideAll = 'Do you want to hide all the records?';
$lang->action->needEdit = '%s that you want to restore. Please edit it.';
$lang->action->historyEdit = 'The history EditBy cannot be empty.';
$lang->action->noDynamic = 'No dynamics. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->history = new stdclass();
$lang->action->history->action = 'Link';
+1
View File
@@ -53,6 +53,7 @@ $lang->action->confirmHideAll = '您确定要全部隐藏这些记录吗?';
$lang->action->needEdit = '要还原%s的名称或代号已经存在,请编辑更改。';
$lang->action->historyEdit = '历史记录编辑不能为空。';
$lang->action->noDynamic = '暂时没有动态。';
$lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。';
$lang->action->history = new stdclass();
$lang->action->history->action = '关联日志';
+7
View File
@@ -1429,6 +1429,13 @@ class actionModel extends model
{
$action = $this->getById($actionID);
if($action->action != 'deleted') return;
if($action->objectType == 'execution')
{
$execution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($action->objectID)->fetch();
if($execution->deleted and empty($execution->project)) return print(js::error($this->lang->action->undeletedTips));
}
if($action->objectType == 'product')
{
$product = $this->dao->select('id,name,code,acl')->from(TABLE_PRODUCT)->where('id')->eq($action->objectID)->fetch();
+2 -2
View File
@@ -99,7 +99,7 @@ class api extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$releases = $this->api->getReleaseByQuery($libID, $pager, $sort);
$this->view->releases = $releases;
@@ -185,7 +185,7 @@ class api extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$structs = $this->api->getStructByQuery($libID, $pager, $sort);
@@ -31,7 +31,7 @@
<th><?php echo $lang->block->totalStory . ':';?></th>
<td><?php echo $totalData[$projectID]->allStories;?></td>
<th><?php echo $lang->block->totalPeople . ':';?></th>
<td><?php echo $totalData[$projectID]->teamCount ? html::a($this->createLink('project', 'manageMembers', 'projectID=' . $projectID), $totalData[$projectID]->teamCount) : 0;?></td>
<td><?php echo $totalData[$projectID]->teamCount ? html::a($this->createLink('project', 'team', 'projectID=' . $projectID), $totalData[$projectID]->teamCount) : 0;?></td>
<th><?php echo $lang->block->estimatedHours . ':';?></th>
<td><?php echo $totalData[$projectID]->estimate . $lang->execution->workHour;?></td>
<th><?php echo $lang->block->totalBug. ':';?></th>
+5
View File
@@ -189,6 +189,11 @@ $config->bug->datatable->fieldList['type']['fixed'] = 'no';
$config->bug->datatable->fieldList['type']['width'] = '90';
$config->bug->datatable->fieldList['type']['required'] = 'no';
$config->bug->datatable->fieldList['project']['title'] = 'project';
$config->bug->datatable->fieldList['project']['fixed'] = 'no';
$config->bug->datatable->fieldList['project']['width'] = '120';
$config->bug->datatable->fieldList['project']['required'] = 'no';
$config->bug->datatable->fieldList['execution']['title'] = 'execution';
$config->bug->datatable->fieldList['execution']['fixed'] = 'no';
$config->bug->datatable->fieldList['execution']['width'] = '120';
+3 -2
View File
@@ -148,7 +148,7 @@ class bug extends control
setcookie('qaBugOrder', $orderBy, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -238,6 +238,7 @@ class bug extends control
$this->view->isProjectBug = ($productID and !$this->projectID) ? false : true;
$this->view->modulePairs = $showModule ? $this->tree->getModulePairs($productID, 'bug', $showModule) : array();
$this->view->showBranch = $showBranch;
$this->view->projectPairs = $this->loadModel('project')->getPairsByProgram();
$this->display();
}
@@ -548,7 +549,7 @@ class bug extends control
if($user) $productMembers[$assignedTo] = $user->realname;
}
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch === 'all' ? 0 : $branch);
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, ($branch === 'all' or !isset($branches[$branch])) ? 0 : $branch);
if(empty($moduleOptionMenu)) die(js::locate(helper::createLink('tree', 'browse', "productID=$productID&view=story")));
/* Get products and projects. */
+4 -1
View File
@@ -2697,7 +2697,7 @@ class bugModel extends model
* @access public
* @return void
*/
public function printCell($col, $bug, $users, $builds, $branches, $modulePairs, $executions = array(), $plans = array(), $stories = array(), $tasks = array(), $mode = 'datatable')
public function printCell($col, $bug, $users, $builds, $branches, $modulePairs, $executions = array(), $plans = array(), $stories = array(), $tasks = array(), $mode = 'datatable', $projectPairs = array())
{
/* Check the product is closed. */
$canBeChanged = common::canBeChanged('bug', $bug);
@@ -2809,6 +2809,9 @@ class bugModel extends model
case 'branch':
echo zget($branches, $bug->branch, '');
break;
case 'project':
echo zget($projectPairs, $bug->project, '');
break;
case 'execution':
echo zget($executions, $bug->execution, '');
break;
+1 -1
View File
@@ -306,7 +306,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
}
}?>
<?php else:?>
<?php foreach($setting as $value) $this->bug->printCell($value, $bug, $users, $builds, $branchOption, $modulePairs, $executions, $plans, $stories, $tasks, $useDatatable ? 'datatable' : 'table');?>
<?php foreach($setting as $value) $this->bug->printCell($value, $bug, $users, $builds, $branchOption, $modulePairs, $executions, $plans, $stories, $tasks, $useDatatable ? 'datatable' : 'table', $projectPairs);?>
<?php endif;?>
</tr>
<?php endforeach;?>
+1 -1
View File
@@ -289,7 +289,7 @@
<td>
<?php
if($bug->story) echo html::a($this->createLink('story', 'view', "storyID=$bug->story", '', true), "#$bug->story $bug->storyTitle", '', "class='iframe' data-width='80%'");
if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion)
if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion and common::hasPriv('bug', 'confirmStoryChange'))
{
echo "(<span class='warning'>{$lang->story->changed}</span> ";
echo html::a($this->createLink('bug', 'confirmStoryChange', "bugID=$bug->id"), $lang->confirm, 'hiddenwin');
+1 -1
View File
@@ -203,7 +203,7 @@ class caselib extends control
$this->caselib->buildSearchForm($libID, $libraries, $queryID, $actionURL);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* save session .*/
$cases = $this->caselib->getLibCases($libID, $browseType, $queryID, $moduleID, $sort, $pager);
+1 -1
View File
@@ -2022,7 +2022,7 @@ EOD;
* @access public
* @return string
*/
public function appendOrder($orderBy, $append = 'id')
public static function appendOrder($orderBy, $append = 'id')
{
if(empty($orderBy)) return $append;
-23
View File
@@ -1,24 +1 @@
<?php if($extView = $this->getExtViewFile(__FILE__)){include $extView; return helper::cd();}?>
<?php if($config->debug):?>
<?php css::import($jsRoot . 'zui/picker/zui.picker.min.css'); ?>
<?php js::import($jsRoot . 'zui/picker/zui.picker.min.js'); ?>
<?php endif;?>
<style>
.picker-single .picker-selection-remove{z-index: 1000;}
.picker-selection-single:after, .picker-multi.picker-focus .picker-selections:before{font-family: ZentaoIcon !important; content: '\f0d7' !important;}
</style>
<script>
var chooseUsersToMail = '<?php echo $lang->chooseUsersToMail;?>';
if($.fn.picker)
{
$(document).ready(function()
{
$(".picker-select[data-pickertype!='remote']").picker({chosenMode: true});
$("[data-pickertype='remote']").each(function()
{
var pickerremote = $(this).attr('data-pickerremote');
$(this).picker({chosenMode: true, remote: pickerremote});
})
});
}
</script>
+2 -2
View File
@@ -63,7 +63,7 @@ class company extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Build the search form. */
$queryID = $type == 'bydept' ? 0 : (int)$param;
@@ -205,7 +205,7 @@ class company extends control
/* Append id for secend sort. */
$order = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($order);
$sort = common::appendOrder($order);
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
$date = empty($date) ? '' : date('Y-m-d', $date);
+8
View File
@@ -0,0 +1,8 @@
$(function()
{
$('#modeTab').addClass('btn-active-text');
$('[name=mode]').change(function()
{
$(this).val() == 'new' ? $('#changeModeTips').removeClass('hidden') : $('#changeModeTips').addClass('hidden');
});
})
+1
View File
@@ -220,6 +220,7 @@ $lang->custom->menuTip = 'Click to show/hide the menu. Drag to switch d
$lang->custom->saveFail = 'Failed to save!';
$lang->custom->page = ' Page';
$lang->custom->changeClassicTip = 'The Program module will be hidden, if you switch to the classic mode.';
$lang->custom->changeModeTips = 'Historical deleted data does not participate in the data merging process. After switching the mode, it will not support restoration. Please know.';
$lang->custom->scoreStatus[1] = 'On';
$lang->custom->scoreStatus[0] = 'Off';
+1
View File
@@ -220,6 +220,7 @@ $lang->custom->menuTip = '点击显示或隐藏导航条目,拖拽来
$lang->custom->saveFail = '保存失败!';
$lang->custom->page = '页面';
$lang->custom->changeClassicTip = '切换为老版本的习惯后,系统将取消项目集功能。';
$lang->custom->changeModeTips = '历史删除数据不参与数据归并流程,切换模式后将不支持还原,请知悉';
$lang->custom->scoreStatus[1] = '开启';
$lang->custom->scoreStatus[0] = '关闭';
+4 -4
View File
@@ -32,12 +32,12 @@
</tr>
<tr>
<td></td>
<td><?php if($changedMode != 'yes') echo html::submitButton($lang->custom->switch);?></td>
<td>
<?php if($changedMode != 'yes') echo html::submitButton($lang->custom->switch);?>
<div id='changeModeTips' class='text-danger hidden'><?php echo $lang->custom->changeModeTips;?></div>
</td>
</tr>
</table>
</form>
</div>
<script>
$('#modeTab').addClass('btn-active-text');
</script>
<?php include '../../common/view/footer.html.php';?>
+32 -1
View File
@@ -92,7 +92,7 @@ class doc extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
if($browseType == 'collectedbyme')
{
@@ -778,6 +778,37 @@ class doc extends control
$this->doc->saveDraft($docID);
}
/**
* Ajax get doclib whitelist.
*
* @param int $doclibID
* @param string $acl open|custom|private
* @access public
* @return string
*/
public function ajaxGetWhitelist($doclibID, $acl)
{
$doclib = $this->doc->getLibById($doclibID);
$users = $this->user->getPairs('noletter|noempty|noclosed');
if($doclib->acl != 'custom' and !empty($doclib->project) and $acl == 'custom')
{
$project = $this->loadModel('project')->getById($doclib->project);
$userList = array();
$projectTeams = $this->loadModel('user')->getTeamMemberPairs($doclib->project);
$stakeholders = $this->loadModel('stakeholder')->getStakeHolderPairs($doclib->project);
foreach($stakeholders as $stakeholder) $userList[$stakeholder] = $users[$stakeholder];
$userList += $projectTeams;
$whitelist = implode(',', array_keys($userList)) . $project->whitelist . ',' .$project->PM . ',' . $doclib->users;
return print(html::select('users[]', $users, $whitelist, "class='form-control chosen' multiple"));
}
return print(html::select('users[]', $users, $doclib->users, "class='form-control chosen' multiple"));
}
/**
* Show files.
*
+20
View File
@@ -24,16 +24,36 @@ function toggleAcl(acl, type)
if(acl == 'custom')
{
$('#whiteListBox').removeClass('hidden');
$('#groupWhiteListBox').removeClass('hidden');
}
else if(acl == 'private')
{
$('#whiteListBox').removeClass('hidden');
$('#groupWhiteListBox').addClass('hidden');
}
else
{
$('#whiteListBox').addClass('hidden');
}
if(type == 'lib')
{
var libType = $('input[name="type"]:checked').val();
var notice = typeof(noticeAcl[libType][acl]) != 'undefined' ? noticeAcl[libType][acl] : '';
$('#noticeAcl').html(notice);
if(libType == 'custom' && acl == 'private') $('#whiteListBox').addClass('hidden');
if(libType == 'project' && typeof(doclibID) != 'undefined')
{
link = createLink('doc', 'ajaxGetWhitelist', 'doclibID=' + doclibID + '&acl=' + acl);
$.get(link, function(users)
{
$('#users').replaceWith(users);
$('#users_chosen').remove();
$('#users').chosen();
})
}
}
else
{
+3 -1
View File
@@ -206,7 +206,9 @@ $lang->doc->selectLibType = 'Please select a type of doc library.';
$lang->doc->noticeAcl['lib']['product']['default'] = 'Users who can access the selected product can access it.';
$lang->doc->noticeAcl['lib']['product']['custom'] = 'Users who can access the selected product or users in the whiltelist can access it.';
$lang->doc->noticeAcl['lib']['project']['default'] = 'Users who can access the selected project can access it.';
$lang->doc->noticeAcl['lib']['project']['custom'] = 'Users who can access the selected project or users in the whiltelist can access it.';
$lang->doc->noticeAcl['lib']['project']['open'] = 'Users who can access the selected project can access it.';
$lang->doc->noticeAcl['lib']['project']['private'] = 'Users who can access the selected project or users in the whiltelist can access it.';
$lang->doc->noticeAcl['lib']['project']['custom'] = 'Users in the whiltelist can access it.';
$lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->executionCommon} can access it.";
$lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->executionCommon} or users in the whiltelist can access it.";
$lang->doc->noticeAcl['lib']['custom']['open'] = 'All users can access it.';
+3 -1
View File
@@ -206,7 +206,9 @@ $lang->doc->selectLibType = '请选择文档库类型';
$lang->doc->noticeAcl['lib']['product']['default'] = '有所选产品访问权限的用户可以访问。';
$lang->doc->noticeAcl['lib']['product']['custom'] = '有所选产品访问权限或白名单里的用户可以访问。';
$lang->doc->noticeAcl['lib']['project']['default'] = "有所选项目访问权限的用户可以访问。";
$lang->doc->noticeAcl['lib']['project']['custom'] = "有所选项目访问权限或白名单里的用户可以访问。";
$lang->doc->noticeAcl['lib']['project']['open'] = "有所选项目访问权限的用户可以访问。";
$lang->doc->noticeAcl['lib']['project']['private'] = "有所选项目访问权限或白名单里的用户可以访问。";
$lang->doc->noticeAcl['lib']['project']['custom'] = "白名单的用户可以访问。";
$lang->doc->noticeAcl['lib']['execution']['default'] = "有所选{$lang->executionCommon}访问权限的用户可以访问。";
$lang->doc->noticeAcl['lib']['execution']['custom'] = "有所选{$lang->executionCommon}访问权限或白名单里的用户可以访问。";
$lang->doc->noticeAcl['lib']['custom']['open'] = '所有人都可以访问。';
+47 -17
View File
@@ -177,8 +177,7 @@ class docModel extends model
$lib->project = $execution->project;
}
if($lib->acl == 'private') $lib->users = $this->app->user->account;
if($lib->acl == 'custom')
if($lib->acl == 'custom' or $lib->acl == 'private')
{
$trimedUsers = ',' . trim($lib->users, ',') . ',';
if(strpos($trimedUsers, ',' . $this->app->user->account . ',') === false) $lib->users .= ',' . $this->app->user->account;
@@ -254,10 +253,20 @@ class docModel extends model
->join('groups', ',')
->join('users', ',')
->get();
if($lib->acl == 'private')
if($oldLib->type == 'project' or $oldLib->type == 'custom')
{
$libCreatedBy = $this->dao->select('*')->from(TABLE_ACTION)->where('objectType')->eq('doclib')->andWhere('objectID')->eq($libID)->andWhere('action')->eq('created')->fetch('actor');
$lib->users = $libCreatedBy ? $libCreatedBy : $this->app->user->account;
if($oldLib->type == 'custom')
{
if($lib->acl == 'private') $lib->users = $libCreatedBy ? $libCreatedBy : $this->app->user->account;
}
else
{
$openedBy = $this->dao->findById($oldLib->project)->from(TABLE_PROJECT)->fetch('openedBy');
if($lib->acl == 'private' and $lib->acl == 'custom') $lib->users .= ',' . $libCreatedBy ? $libCreatedBy : $openedBy;
}
}
$lib->name = trim($lib->name); //Temporary treatment: Code for bug #15528.
@@ -906,11 +915,17 @@ class docModel extends model
if(isset($object->addedBy) and $object->addedBy == $this->app->user->account) return true;
if(isset($object->users) and strpos(",{$object->users},", $account) !== false) return true;
if($object->project and $object->main)
if($object->project and $object->acl == 'private')
{
$stakeHolders = array();
$project = $this->loadModel('project')->getById($object->project);
$projectTeams = $this->loadModel('user')->getTeamMemberPairs($object->project);
$authorizedUsers = $this->user->getProjectAuthedUsers($project, '', $projectTeams, array_flip(explode(",", $project->whitelist)));
$stakeHolderList = $this->loadModel('stakeholder')->getStakeHolderPairs($object->project);
foreach($stakeHolderList as $stakeHolder) $stakeHolders[$stakeHolder] = $stakeHolder;
$authorizedUsers = $this->user->getProjectAuthedUsers($project, $stakeHolders, $projectTeams, array_flip(explode(",", $project->whitelist)));
if(strpos(",{$object->users},", $account) !== false) return true;
if(array_key_exists($this->app->user->account, array_filter($authorizedUsers))) return true;
}
@@ -1318,6 +1333,15 @@ class docModel extends model
/* Sort project. */
$orderedProjects = array();
/* Project permissions for DocLib whitelist */
if($this->app->tab == 'doc')
{
$myObjects = $this->dao->select('t2.id, t2.name')->from(TABLE_DOCLIB)->alias('t1')
->leftjoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where("CONCAT(',', t1.users, ',')")->like("%,{$this->app->user->account},%")
->fetchPairs();
}
$objects = $this->dao->select('*')->from(TABLE_PROJECT)
->where('type')->eq('project')
->andWhere('deleted')->eq(0)
@@ -1905,28 +1929,34 @@ class docModel extends model
*/
public function buildCreateButton4Doc($objectType, $objectID, $libID)
{
if(!common::hasPriv('doc', 'create') and !common::hasPriv('doc', 'createLib')) return '';
if($objectType == 'book')
{
$html = html::a(helper::createLink('doc', 'createLib', "type=$objectType&objectID=$objectID"), '<i class="icon icon-plus"></i> ' . $this->lang->doc->createBook, '', 'class="btn btn-secondary iframe"');
}
elseif($libID)
{
$html = "<div class='dropdown' id='createDropdown'>";
$html = "<div class='dropdown' id='createDropdown'>";
$html .= "<button class='btn btn-primary' type='button' data-toggle='dropdown'><i class='icon icon-plus'></i> " . $this->lang->doc->createAB . " <span class='caret'></span></button>";
$html .= "<ul class='dropdown-menu pull-right'>";
foreach($this->lang->doc->typeList as $typeKey => $typeName)
if(common::hasPriv('doc', 'create'))
{
$class = strpos($this->config->doc->officeTypes, $typeKey) !== false ? 'iframe' : '';
$icon = zget($this->config->doc->iconList, $typeKey);
$html .= "<li>";
$html .= html::a(helper::createLink('doc', 'create', "objectType=$objectType&objectID=$objectID&libID=$libID&moduleID=0&type=$typeKey", '', $class ? true : false), "<i class='icon-$icon icon'></i> " . $typeName, '', "class='$class' data-app='{$this->app->tab}'");
$html .= "</li>";
if($typeKey == 'url') $html .= '<li class="divider"></li>';
foreach($this->lang->doc->typeList as $typeKey => $typeName)
{
$class = strpos($this->config->doc->officeTypes, $typeKey) !== false ? 'iframe' : '';
$icon = zget($this->config->doc->iconList, $typeKey);
$html .= "<li>";
$html .= html::a(helper::createLink('doc', 'create', "objectType=$objectType&objectID=$objectID&libID=$libID&moduleID=0&type=$typeKey", '', $class ? true : false), "<i class='icon-$icon icon'></i> " . $typeName, '', "class='$class' data-app='{$this->app->tab}'");
$html .= "</li>";
if($typeKey == 'url') $html .= '<li class="divider"></li>';
}
}
if(common::hasPriv('doc', 'createLib'))
{
$html .= '<li class="divider"></li>';
if(common::hasPriv('doc', 'create')) $html .= '<li class="divider"></li>';
$html .= '<li>' . html::a(helper::createLink('doc', 'createLib', "type=$objectType&objectID=$objectID"), "<i class='icon-doc-lib icon'></i> " . $this->lang->doc->createLib, '', "class='iframe' data-width='70%'") . '</li>';
}
$html .= "</ul></div>";
@@ -2579,8 +2609,8 @@ EOT;
$tab = strpos(',doc,product,project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'doc';
if($tab != 'doc') $this->loadModel($tab)->setMenu($objectID);
$this->lang->TRActions = $this->buildCollectButton4Doc();
$this->lang->TRActions .= common::hasPriv('doc', 'create') ? $this->buildCreateButton4Doc($type, $objectID, $libID) : '';
$this->lang->TRActions = $this->buildCollectButton4Doc();
$this->lang->TRActions .= $this->buildCreateButton4Doc($type, $objectID, $libID);
return array($libs, $libID, $object, $objectID);
}
+1 -1
View File
@@ -59,7 +59,7 @@
<tr id='whiteListBox' class='hidden'>
<th><?php echo $lang->doc->whiteList;?></th>
<td>
<div class='input-group'>
<div id='groupWhiteListBox' class='input-group'>
<span class='input-group-addon groups-addon'><?php echo $lang->doclib->group?></span>
<?php echo html::select('groups[]', $groups, '', "class='form-control chosen' multiple")?>
</div>
+2 -1
View File
@@ -12,6 +12,7 @@
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php include '../../common/view/chosen.html.php';?>
<?php js::set('doclibID', $lib->id);?>
<?php if($lib->type == 'product'):?>
<style> .chosen-container .chosen-results {max-height: 180px;}</style>
<?php else:?>
@@ -63,7 +64,7 @@
<tr id='whiteListBox' class='hidden'>
<th><?php echo $lang->doc->whiteList?></th>
<td>
<div class='input-group'>
<div id='groupWhiteListBox' class='input-group'>
<span class='input-group-addon groups-addon'><?php echo $lang->doclib->group?></span>
<?php echo html::select('groups[]', $groups, $lib->groups, "class='form-control chosen' multiple")?>
</div>
+9 -12
View File
@@ -175,7 +175,7 @@ class execution extends control
setcookie('executionTaskOrder', $orderBy, 0, $this->config->webRoot, '', false, true);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Header and position. */
$this->view->title = $execution->name . $this->lang->colon . $this->lang->execution->task;
@@ -268,7 +268,7 @@ class execution extends control
/* Get tasks and group them. */
if(empty($groupBy))$groupBy = 'story';
if(($groupBy == 'story') and ($execution->type == 'ops'))$groupBy = 'status';
$sort = $this->loadModel('common')->appendOrder($groupBy);
$sort = common::appendOrder($groupBy);
$tasks = $this->loadModel('task')->getExecutionTasks($executionID, $productID = 0, $status = 'all', $modules = 0, $sort);
$groupBy = str_replace('`', '', $groupBy);
$taskLang = $this->lang->task;
@@ -730,7 +730,7 @@ class execution extends control
setcookie('executionStoryOrder', $orderBy, 0, $this->config->webRoot, '', false, true);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$queryID = ($type == 'bysearch') ? $param : 0;
$execution = $this->commonAction($executionID);
@@ -885,7 +885,7 @@ class execution extends control
$this->app->loadClass('pager', $static = true);
if($this->app->getViewType() == 'xhtml') $recPerPage = 10;
$pager = new pager($recTotal, $recPerPage, $pageID);
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$bugs = $this->bug->getExecutionBugs($executionID, $productID, $build, $type, $param, $sort, '', $pager);
$bugs = $this->bug->checkDelayedBugs($bugs);
$users = $this->user->getPairs('noletter');
@@ -1972,13 +1972,10 @@ class execution extends control
foreach($plans as $plan) $allPlans += $plan;
}
$userList = array();
$avatarPairs = $this->dao->select('account, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchPairs();
foreach($avatarPairs as $account => $avatar)
{
if(!$avatar) continue;
$userList[$account]['avatar'] = $avatar;
}
$userList = $this->dao->select('account, realname name, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchAll('account');
$userList['closed']['account'] = 'Closed';
$userList['closed']['name'] = 'Closed';
$userList['closed']['avatar'] = '';
$this->view->title = $this->lang->execution->kanban;
$this->view->position[] = html::a($this->createLink('execution', 'browse', "executionID=$executionID"), $execution->name);
@@ -2743,7 +2740,7 @@ class execution extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Set the menu. If the executionID = 0, use the indexMenu instead. */
$this->execution->setMenu($executionID);
+1 -1
View File
@@ -39,7 +39,7 @@ function renderUserAvatar(user, objectType, objectID, size)
if(objectType == 'story' && !priv.canAssignStory) return $noPrivAvatar;
if(objectType == 'bug' && !priv.canAssignBug) return $noPrivAvatar;
return $('<a class="avatar has-text ' + avatarSizeClass + ' avatar-circle iframe" href="' + link + '"/>').avatar({user: user});
return $('<a class="avatar has-text ' + avatarSizeClass + ' avatar-circle iframe" title="' + user.name + '" href="' + link + '"/>').avatar({user: user});
}
/**
+3 -3
View File
@@ -329,7 +329,7 @@ class executionModel extends model
->join('whitelist', ',')
->add('type', $type)
->stripTags($this->config->execution->editor->create['id'], $this->config->allowedTags)
->remove('products, workDays, delta, branch, uid, plans, teams, teamMembers')
->remove('products, workDays, delta, branch, uid, plans, teams, teamMembers, contactListMenu')
->get();
/* Check the workload format and total. */
@@ -487,7 +487,7 @@ class executionModel extends model
->setDefault('team', $this->post->name)
->join('whitelist', ',')
->stripTags($this->config->execution->editor->edit['id'], $this->config->allowedTags)
->remove('products, branch, uid, plans, syncStories')
->remove('products, branch, uid, plans, syncStories, contactListMenu')
->get();
if($this->config->systemMode == 'new' and (empty($execution->project) or $execution->project == $oldExecution->project)) $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end);
@@ -1324,7 +1324,7 @@ class executionModel extends model
$module = 'execution';
$method = 'testcase';
}
if($module == 'testtask' and ($method == 'view' || $method == 'create' || $method == 'edit'))
if($module == 'testtask' and ($method == 'view' || $method == 'create' || $method == 'edit' || $method == 'linkcase'))
{
$module = 'execution';
$method = 'testtask';
+6 -3
View File
@@ -227,9 +227,12 @@
</tr>
<tr class="hidden" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $whitelist, 'class="form-control chosen" multiple');?></td>
<td></td>
<td></td>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
+6 -2
View File
@@ -191,8 +191,12 @@
</tr>
<tr class="<?php if($execution->acl == 'open') echo 'hidden';?>" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $execution->whitelist, 'class="form-control chosen" multiple');?></td>
<td></td>
<td>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $execution->whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr><td colspan='3' class='text-center form-actions'><?php echo html::submitButton() . ' ' . html::backButton();?></td></tr>
</table>
+2
View File
@@ -25,10 +25,12 @@
<th><?php echo $lang->group->desc;?></th>
<td><?php echo html::textarea('desc', '', "rows=5 class=form-control");?></td>
</tr>
<?php if($this->app->tab != 'project'):?>
<tr>
<th><?php echo $lang->group->limited;?></th>
<td><?php echo html::checkbox('limited', '');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='2' class='text-center'><?php echo html::submitButton();?></td>
</tr>
+1 -1
View File
@@ -91,7 +91,7 @@
$userCount = count($assignedToList);
?>
<?php if($userCount > 0):?>
<div class='users pull-right' title="<?php echo $members;?>">
<div class='users pull-right' title="<?php echo trim($members, ',');?>">
<?php
foreach($assignedToList as $account)
{
+132 -11
View File
@@ -86,9 +86,128 @@ class my extends control
*/
public function work($mode = 'task', $type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->showWorkCount($orderBy, $recTotal, $recPerPage, $pageID);
echo $this->fetch('my', $mode, "type=$type&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
}
/**
* Show to-do work count.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function showWorkCount($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->loadModel('task');
$this->loadModel('story');
$this->loadModel('bug');
$this->loadModel('testcase');
$this->loadModel('testtask');
/* Load pager. */
$this->app->loadClass('pager', $static = true);
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Get the number of tasks assigned to me. */
$tasks = $this->task->getUserTasks($this->app->user->account, 'assignedTo', 0, $pager);
$taskCount = $pager->recTotal;
/* Get the number of stories assigned to me. */
$assignedToStories = $this->story->getUserStories($this->app->user->account, 'assignedTo', $orderBy, $pager, 'story', false);
$assignedToStoryCount = $pager->recTotal;
$reviewByStories = $this->story->getUserStories($this->app->user->account, 'reviewBy', $orderBy, $pager, 'story', false);
$reviewByStoryCount = $pager->recTotal;
$storyCount = $assignedToStoryCount + $reviewByStoryCount;
$requirementCount = 0;
$isOpenedURAndSR = $this->config->URAndSR;
if($isOpenedURAndSR)
{
/* Get the number of requirements assigned to me. */
$assignedRequirements = $this->story->getUserStories($this->app->user->account, 'assignedTo', $orderBy, $pager, 'requirement');
$assignedRequirementCount = $pager->recTotal;
$reviewByRequirements = $this->story->getUserStories($this->app->user->account, 'reviewBy', $orderBy, $pager, 'requirement');
$reviewByRequirementCount = $pager->recTotal;
$requirementCount = $assignedRequirementCount + $reviewByRequirementCount;
}
/* Get the number of bugs assigned to me. */
$bugs = $this->bug->getUserBugs($this->app->user->account, 'assignedTo', $orderBy, 0, $pager);
$bugCount = $pager->recTotal;
/* Get the number of testcases assigned to me. */
$cases = $this->testcase->getByAssignedTo($this->app->user->account, $orderBy, $pager, 'skip');
$caseCount = $pager->recTotal;
/* Get the number of testtasks assigned to me. */
$testTasks = $this->testtask->getByUser($this->app->user->account, $pager, $orderBy, 'assignedTo');
$testTaskCount = $pager->recTotal;
$issueCount = 0;
$riskCount = 0;
$reviewCount = 0;
$ncCount = 0;
$meetingCount = 0;
$isMaxVersion = isset($this->config->maxVersion) ? 1 : 0;
if($isMaxVersion)
{
$this->loadModel('issue');
$this->loadModel('risk');
$this->loadModel('review');
$this->loadModel('meeting');
/* Get the number of issues assigned to me. */
$issues = $this->issue->getUserIssues('assignedTo', $this->app->user->account, $orderBy, $pager);
$issueCount = $pager->recTotal;
/* Get the number of risks assigned to me. */
$risks = $this->risk->getUserRisks('assignedTo', $this->app->user->account, $orderBy, $pager);
$riskCount = $pager->recTotal;
/* Get the number of reviews assigned to me. */
$reviewList = $this->review->getUserReviews('wait', $orderBy, $pager);
$reviewCount = $pager->recTotal;
/* Get the number of nc assigned to me. */
$ncList = $this->my->getNcList('assignedToMe', $orderBy, $pager);
$ncCount = $pager->recTotal;
/* Get the number of meetings assigned to me. */
$meetings = $this->meeting->getListByUser('futureMeeting', $orderBy, 0, $pager);
$meetingCount = $pager->recTotal;
}
echo <<<EOF
<script>
var taskCount = $taskCount;
var storyCount = $storyCount;
var bugCount = $bugCount;
var caseCount = $caseCount;
var testTaskCount = $testTaskCount;
var isOpenedURAndSR = $isOpenedURAndSR;
if(isOpenedURAndSR !== 0) var requirementCount = $requirementCount;
var isMaxVersion = $isMaxVersion;
if(isMaxVersion !== 0)
{
var issueCount = $issueCount;
var riskCount = $riskCount;
var reviewCount = $reviewCount;
var ncCount = $ncCount;
var meetingCount = $meetingCount;
}
</script>
EOF;
}
/**
* My contribute view.
*
@@ -145,7 +264,7 @@ class my extends control
$this->view->position[] = $this->lang->my->todo;
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$todos = $this->loadModel('todo')->getList($type, $account, $status, 0, $pager, $sort);
$tasks = $this->loadModel('task')->getUserSuspendedTasks($account);
@@ -198,7 +317,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'story', false);
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
@@ -242,7 +361,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type, $sort, $pager, 'requirement');
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
@@ -286,7 +405,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Get tasks. */
$tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $type, 0, $pager, $sort);
@@ -361,7 +480,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$bugs = $this->loadModel('bug')->getUserBugs($this->app->user->account, $type, $sort, 0, $pager);
$bugs = $this->bug->checkDelayedBugs($bugs);
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', false);
@@ -413,7 +532,7 @@ class my extends control
$this->app->loadLang('testcase');
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->testTask;
$this->view->position[] = $this->lang->my->testTask;
@@ -456,7 +575,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$cases = array();
if($type == 'assigntome')
@@ -505,7 +624,7 @@ class my extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$docs = $this->doc->getDocsByBrowseType($type, 0, 0, $sort, $pager);
@@ -791,7 +910,7 @@ class my extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Get users by dept. */
$user = $this->loadModel('user')->getById($this->app->user->account, 'account');
@@ -968,12 +1087,14 @@ class my extends control
/**
* Build contact lists.
*
* @param dropdownName
* @access public
* @return void
*/
public function buildContactLists()
public function buildContactLists($dropdownName = 'mailto')
{
$this->view->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote');
$this->view->dropdownName = $dropdownName;
$this->display();
}
@@ -1086,7 +1207,7 @@ class my extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* The header and position. */
$this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->dynamic;
+21 -2
View File
@@ -3,9 +3,28 @@ $(function()
if(typeof mode === 'string')
{
$('#subNavbar li[data-id=' + mode + ']').addClass('active');
if(typeof rawMethod === 'string' && rawMethod == 'work') $('#subNavbar li[data-id=' + mode + '] a').append('<span class="label label-light label-badge">' + total + '</span>');
if(typeof rawMethod === 'string' && rawMethod == 'work')
{
$("#subNavbar li[data-id='task'] a").append('<span class="label label-light label-badge">' + taskCount + '</span>');
$("#subNavbar li[data-id='story'] a").append('<span class="label label-light label-badge">' + storyCount + '</span>');
$("#subNavbar li[data-id='bug'] a").append('<span class="label label-light label-badge">' + bugCount + '</span>');
$("#subNavbar li[data-id='testcase'] a").append('<span class="label label-light label-badge">' + caseCount + '</span>');
$("#subNavbar li[data-id='testtask'] a").append('<span class="label label-light label-badge">' + testTaskCount + '</span>');
if(isOpenedURAndSR !== 0) $("#subNavbar li[data-id='requirement'] a").append('<span class="label label-light label-badge">' + requirementCount + '</span>');
if(isMaxVersion !== 0)
{
$("#subNavbar li[data-id='issue'] a").append('<span class="label label-light label-badge">' + issueCount + '</span>');
$("#subNavbar li[data-id='risk'] a").append('<span class="label label-light label-badge">' + riskCount + '</span>');
$("#subNavbar li[data-id='audit'] a").append('<span class="label label-light label-badge">' + reviewCount + '</span>');
$("#subNavbar li[data-id='nc'] a").append('<span class="label label-light label-badge">' + ncCount + '</span>');
$("#subNavbar li[data-id='myMeeting'] a").append('<span class="label label-light label-badge">' + meetingCount + '</span>');
}
}
}
var $scp = $('[data-id="changePassword"] a');
var $scp = $('[data-id="changePassword"] a');
if($scp.length > 0)
{
var sign = config.requestType == 'GET' ? '&' : '?';
+3 -3
View File
@@ -13,7 +13,7 @@
<?php
if($contactLists)
{
echo html::select('contactListMenu', $contactLists, '', "class='form-control chosen' onchange=\"setMailto('mailto', this.value)\"");
echo html::select('contactListMenu', $contactLists, '', "class='form-control chosen' onchange=\"setMailto($dropdownName, this.value)\"");
}
else
{
@@ -28,7 +28,7 @@ else
<style>
#contactListMenu_chosen {width: 100px !important;}
#contactListMenu + .chosen-container {min-width: 100px;}
td > #mailto + .chosen-container .chosen-choices {border-radius: 2px 2px 0 0;}
td > #mailto + .chosen-container + #contactListMenu + .chosen-container > .chosen-single {border-radius: 0 0 2px 2px; border-top-width: 0; padding-top: 6px;}
td > <?php echo "#" . $dropdownName;?> + .chosen-container .chosen-choices {border-radius: 2px 2px 0 0;}
td > <?php echo "#" . $dropdownName;?> + .chosen-container + #contactListMenu + .chosen-container > .chosen-single {border-radius: 0 0 2px 2px; border-top-width: 0; padding-top: 6px;}
#contactListMenu + .chosen-container.chosen-container-active > .chosen-single {border-top-width: 1px !important; padding-top: 5px !important;}
</style>
+2 -2
View File
@@ -214,7 +214,7 @@ class product extends control
setcookie('productStoryOrder', $orderBy, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -843,7 +843,7 @@ class product extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
+2 -2
View File
@@ -577,7 +577,7 @@ class productModel extends model
->stripTags($this->config->product->editor->create['id'], $this->config->allowedTags)
->join('whitelist', ',')
->join('reviewer', ',')
->remove('uid,newLine,lineName')
->remove('uid,newLine,lineName,contactListMenu')
->get();
if(!empty($_POST['lineName']))
@@ -653,7 +653,7 @@ class productModel extends model
->join('whitelist', ',')
->join('reviewer', ',')
->stripTags($this->config->product->editor->edit['id'], $this->config->allowedTags)
->remove('uid,changeProjects')
->remove('uid,changeProjects,contactListMenu')
->get();
if($this->config->systemMode == 'new')
+1 -1
View File
@@ -599,7 +599,7 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
</div>
<div class="modal-body">
<div class='input-group'>
<?php echo html::select('plan', $productPlans[$productID], '', "class='form-control chosen' id='plan'");?>
<?php echo html::select('plan', zget($productPlans, $productID, ''), '', "class='form-control chosen' id='plan'");?>
<span class='input-group-btn'><?php echo html::commonButton($lang->execution->linkStory, "id='toTaskButton'", 'btn btn-primary');?></span>
</div>
</div>
+6 -2
View File
@@ -104,8 +104,12 @@
</tr>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
<td></td>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'>
+6 -2
View File
@@ -87,8 +87,12 @@
</tr>
<tr class="<?php if($product->acl == 'open') echo 'hidden';?>" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $product->whitelist, 'class="form-control chosen" multiple');?></td>
<td></td>
<td>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $product->whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'>
+2 -2
View File
@@ -248,7 +248,7 @@ class productplan extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->session->set('productPlanList', $this->app->getURI(true), 'product');
$viewType = $this->cookie->viewType ? $this->cookie->viewType : 'list';
@@ -344,7 +344,7 @@ class productplan extends control
if($this->app->getViewType() == 'xhtml') $recPerPage = 10;
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->commonAction($plan->product, $plan->branch);
$products = $this->product->getProductPairsByProject($this->session->project);
+2 -2
View File
@@ -593,7 +593,7 @@ class programModel extends model
->add('type', 'program')
->join('whitelist', ',')
->stripTags($this->config->program->editor->create['id'], $this->config->allowedTags)
->remove('delta,future')
->remove('delta,future,contactListMenu')
->get();
if($program->parent)
@@ -678,7 +678,7 @@ class programModel extends model
->setIF(!isset($this->post->budgetUnit), 'budgetUnit', $oldProgram->budgetUnit)
->join('whitelist', ',')
->stripTags($this->config->program->editor->edit['id'], $this->config->allowedTags)
->remove('uid,delta,future,syncPRJUnit,exchangeRate')
->remove('uid,delta,future,syncPRJUnit,exchangeRate,contactListMenu')
->get();
$program = $this->loadModel('file')->processImgURL($program, $this->config->program->editor->edit['id'], $this->post->uid);
+6 -3
View File
@@ -114,9 +114,12 @@
</tr>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
<td></td>
<td></td>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
+6 -3
View File
@@ -99,9 +99,12 @@
</tr>
<tr class="<?php if($program->acl == 'open') echo 'hidden';?>" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $program->whitelist, 'class="form-control chosen" multiple');?></td>
<td></td>
<td></td>
<td>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $program->whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
+1 -1
View File
@@ -88,7 +88,7 @@ class programplan extends control
if($type == 'lists')
{
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->loadModel('datatable');
$plans = $this->programplan->getPlans($projectID, $this->productID, $sort);
}
+10 -5
View File
@@ -125,11 +125,16 @@ $config->project->datatable->fieldList['actions']['width'] = '180';
$config->project->datatable->fieldList['actions']['required'] = 'yes';
$config->project->datatable->fieldList['actions']['pri'] = '1';
$config->project->removePriv['project'] = array('index', 'browse', 'kanban', 'create', 'batchEdit', 'qa', 'updateOrder', 'createGuide', 'programTitle');
$config->project->removePriv['bug'] = array('batchChangePlan');
$config->project->removePriv['doc'] = array('catalog', 'index');
$config->project->removePriv['auditplan'] = array('delete');
$config->project->checkList = new stdclass();
$config->project->checkList->scrum = array('bug', 'execution', 'meeting', 'release', 'build', 'doc', 'testtask', 'risk', 'issue', 'case');
$config->project->checkList->waterfall = array('execution', 'design', 'doc', 'bug', 'case', 'build', 'release', 'testtask', 'review', 'build', 'researchplan', 'issue', 'risk', 'opportunity', 'auditplan', 'gapanalysis', 'meeting');
$config->project->removePriv['project'] = array('index', 'browse', 'kanban', 'create', 'batchEdit', 'qa', 'updateOrder', 'createGuide', 'programTitle', 'export');
$config->project->removePriv['bug'] = array('browse', 'batchChangePlan', 'batchCreate', 'batchEdit', 'batchConfirm', 'batchResolve', 'batchClose', 'batchActivate', 'report', 'batchChangeModule', 'batchChangeBranch');
$config->project->removePriv['testcase'] = array('browse', 'batchChangeModule', 'batchChangeBranch');
$config->project->removePriv['testtask'] = array('browse', 'view', 'start', 'activate', 'block', 'close');
$config->project->removePriv['doc'] = array('catalog', 'index');
$config->project->removePriv['repo'] = array('edit', 'delete', 'maintain', 'setRules');
$config->project->removePriv['testreport'] = array('browse');
$config->project->removePriv['auditplan'] = array('delete');
if(!isset($config->maxVersion)) $config->project->removePriv['stakeholder'] = array('issue', 'viewIssue', 'userIssue');
+4 -2
View File
@@ -808,7 +808,7 @@ class project extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Set the pager. */
$this->app->loadClass('pager', $static = true);
@@ -925,7 +925,7 @@ class project extends control
/* Load pager and get bugs, user. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$bugs = $this->bug->getProjectBugs($projectID, $productID, $build, $type, $param, $sort, '', $pager);
$users = $this->user->getPairs('noletter');
@@ -1321,6 +1321,7 @@ class project extends control
$users = $this->user->getPairs('noclosed|nodeleted|devfirst|nofeedback');
$roles = $this->user->getUserRoles(array_keys($users));
$deptUsers = $dept === '' ? array() : $this->dept->getDeptUserPairs($dept);
$userInfos = $this->user->getUserDisplayInfos(array_keys($users), $dept);
$currentMembers = $this->project->getTeamMembers($projectID);
$members2Import = $this->project->getMembers2Import($copyProjectID, array_keys($currentMembers));
@@ -1331,6 +1332,7 @@ class project extends control
$this->view->project = $project;
$this->view->users = $users;
$this->view->deptUsers = $deptUsers;
$this->view->userInfos = $userInfos;
$this->view->roles = $roles;
$this->view->dept = $dept;
$this->view->depts = array('' => '') + $this->dept->getOptionMenu();
+7 -9
View File
@@ -36,7 +36,7 @@ function saveMembers()
$('#submit').removeClass('hidden');
if(result) $('#removeExecution').val('yes');
$('#submit').click();
})
});
}
}
@@ -50,9 +50,7 @@ function saveMembers()
*/
function setRole(account, roleID)
{
role = roles[account]; // get role according the account.
roleOBJ = $(document.getElementById('roles[' + roleID + ']')); // get role object.
roleOBJ.val(role) // set the role.
$('#roles\\[' + roleID + '\\]').val(roles[account]);
}
/**
@@ -65,11 +63,11 @@ function setRole(account, roleID)
function addItem(obj)
{
var item = $('#addItem').html().replace(/%i%/g, i);
$(obj).closest('tr').after('<tr class="addedItem">' + item + '</tr>');
var accounts = $(obj).closest('tr').next('tr').find('select:first');
accounts.trigger('liszt:updated');
accounts.chosen();
i ++;
var $tr = $('<tr class="addedItem">' + item + '</tr>').insertAfter($(obj).closest('tr'));
$tr.find('select:first')
.trigger('liszt:updated')
.picker({type: 'user'});
i++;
}
/**
+22 -7
View File
@@ -772,7 +772,7 @@ class projectModel extends model
->add('type', 'project')
->join('whitelist', ',')
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
->remove('products,branch,plans,delta,newProduct,productName,future')
->remove('products,branch,plans,delta,newProduct,productName,future,contactListMenu')
->get();
$linkedProductsCount = 0;
@@ -874,9 +874,24 @@ class projectModel extends model
/* Create doc lib. */
$this->app->loadLang('doc');
$authorizedUsers = array();
$authorizedUsers = $project->whitelist . ',' . $project->PM . ',' . $project->openedBy . ',';
$authorizedUsers = array_unique(explode(',', trim($authorizedUsers, ',')));
if($project->parent and $project->acl == 'program')
{
$stakeHolders = $this->loadModel('stakeholder')->getStakeHolderPairs($project->parent);
foreach($stakeHolders as $stakeHolder) $authorizedUsers[$stakeHolder] = $stakeHolder;
foreach(explode(',', $project->whitelist) as $white)
{
if(empty($white)) continue;
$authorizedUsers[$white] = $white;
}
$authorizedUsers[$project->PM] = $project->PM;
$authorizedUsers[$project->openedBy] = $project->openedBy;
$authorizedUsers[$program->PM] = $program->PM;
$authorizedUsers[$program->openedBy] = $program->openedBy;
}
$lib = new stdclass();
$lib->project = $projectID;
@@ -884,7 +899,7 @@ class projectModel extends model
$lib->type = 'project';
$lib->main = '1';
$lib->acl = $project->acl != 'program' ? $project->acl : 'custom';
if($project->acl == 'private') $lib->users = ',' . implode(',', $authorizedUsers) . ',';
$lib->users = ',' . implode(',', array_filter($authorizedUsers)) . ',';
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
$this->updateProducts($projectID);
@@ -985,7 +1000,7 @@ class projectModel extends model
->setIF($this->post->budget != 0, 'budget', round($this->post->budget, 2))
->join('whitelist', ',')
->stripTags($this->config->project->editor->edit['id'], $this->config->allowedTags)
->remove('products,branch,plans,delta,future')
->remove('products,branch,plans,delta,future,contactListMenu')
->get();
if($project->parent)
@@ -2079,8 +2094,8 @@ class projectModel extends model
$this->lang->switcherMenu = $this->getSwitcher($objectID, $this->app->rawModule, $this->app->rawMethod);
/* Reset project priv. */
$moduleName = $this->app->getModuleName();
$methodName = $this->app->getMethodName();
$moduleName = $this->app->rawModule;
$methodName = $this->app->rawMethod;
$this->loadModel('common')->resetProjectPriv($objectID);
if(!$this->common->isOpenMethod($moduleName, $methodName) and !commonModel::hasPriv($moduleName, $methodName)) $this->common->deny($moduleName, $methodName, false);
+6 -3
View File
@@ -159,9 +159,12 @@
</tr>
<tr class="hidden" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
<td></td>
<td></td>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->project->auth;?></th>
+6 -3
View File
@@ -176,9 +176,12 @@
</tr>
<tr class="<?php if($project->acl == 'open') echo 'hidden';?>" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $project->whitelist, 'class="form-control chosen" multiple');?></td>
<td></td>
<td></td>
<td>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $project->whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName='whitelist'");?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->project->auth;?></th>
+3 -2
View File
@@ -2,6 +2,7 @@
<?php js::set('projectID', $project->id);?>
<?php js::set('roles', $roles);?>
<?php js::set('deptID', $dept);?>
<?php js::set('pickerUsers', $userInfos);?>
<?php js::set('copyProjectID', $copyProjectID);?>
<?php js::set('oldAccountList', array_keys($currentMembers));?>
<?php js::set('unlinkExecutionMembers', $lang->project->unlinkExecutionMembers);?>
@@ -75,7 +76,7 @@
<?php foreach($members2Import as $member2Import):?>
<?php if(!isset($users[$member2Import->account])) continue;?>
<tr class='addedItem'>
<td><?php echo html::select("accounts[$i]", $users, $member2Import->account, "class='form-control chosen' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::select("accounts[$i]", $users, $member2Import->account, "class='form-control user-picker' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", $member2Import->role, "class='form-control'");?></td>
<td><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td><?php echo html::input("hours[$i]", $member2Import->hours, "class='form-control'");?></td>
@@ -91,7 +92,7 @@
<?php for($j = 0; $j < 5; $j ++):?>
<tr class='addedItem'>
<td><?php echo html::select("accounts[$i]", $users, '', "class='form-control chosen' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::select("accounts[$i]", $users, '', "class='form-control user-picker' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", '', "class='form-control'");?></td>
<td><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td><?php echo html::input("hours[$i]", $config->execution->defaultWorkhours, "class='form-control'");?></td>
+1 -1
View File
@@ -14,7 +14,7 @@
<?php js::set('confirmDelete', $lang->stakeholder->confirmDelete);?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php echo html::a($this->createLink('stakeholder', 'browse', 'browseType=all'), '<span class="text">' . $lang->stakeholder->browse . '</span>', '', 'class="btn btn-link btn-active-text"');?>
<?php echo html::a($this->createLink('stakeholder', 'browse', "projectID=$projectID"), '<span class="text">' . $lang->stakeholder->browse . '</span>', '', 'class="btn btn-link btn-active-text"');?>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('stakeholder', 'batchcreate') and common::hasPriv('stakeholder', 'create')):?>
+1 -1
View File
@@ -1766,7 +1766,7 @@ class story extends control
}
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->view->title = $this->lang->story->zeroCase;
$this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $products[$productID]);
+3 -2
View File
@@ -2473,8 +2473,9 @@ class storyModel extends model
*/
public function getBySearch($productID, $branch = '', $queryID = 0, $orderBy = '', $executionID = '', $type = 'story', $excludeStories = '', $pager = null)
{
$this->loadModel('product');
$executionID = empty($executionID) ? 0 : $executionID;
$products = $this->loadModel('product')->getProducts($executionID);
$products = empty($executionID) ? $this->product->getList() : $this->product->getProducts($executionID);
$query = $queryID ? $this->loadModel('search')->getQuery($queryID) : '';
@@ -4469,7 +4470,7 @@ class storyModel extends model
public function sortStoriesOfPlan($planID, $sortIDList, $orderBy = 'id_desc', $pageID = 1, $recPerPage = 100)
{
/* Append id for secend sort. */
$orderBy = $this->loadModel('common')->appendOrder($orderBy);
$orderBy = common::appendOrder($orderBy);
/* Get all stories by plan. */
$stories = $this->getPlanStories($planID, 'all', $orderBy);
+2 -1
View File
@@ -481,8 +481,9 @@
{
if(!isset($executions[$task->execution])) continue;
$executionName = $executions[$task->execution];
$taskInfo = $task->id . '&nbsp<span class="label label-success label-outline">' . $this->lang->task->statusList[$task->status] . '</span>&nbsp' . $task->name;
$class = isonlybody() ? 'showinonlybody' : 'iframe';
echo "<li title='$task->name'>" . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), "[T]$task->id $task->name", '', "class=$class data-width='80%'");
echo "<li title='$task->name'>" . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $taskInfo, '', "class=$class data-width='80%'");
echo html::a($this->createLink('execution', 'browse', "executionID=$task->execution"), $executionName, '', "class='text-muted'") . '</li>';
}
}
+1 -1
View File
@@ -1481,7 +1481,7 @@ class task extends control
$taskLang = $this->lang->task;
/* Create field lists. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$fields = $this->post->exportFields ? $this->post->exportFields : explode(',', $allExportFields);
foreach($fields as $key => $fieldName)
{
+2 -2
View File
@@ -137,7 +137,7 @@ class testcase extends control
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Get test cases. */
$cases = $this->testcase->getTestCases($productID, $branch, $browseType, $browseType == 'bysearch' ? $queryID : $suiteID, $moduleID, $sort, $pager);
@@ -480,7 +480,7 @@ class testcase extends control
$this->view->executionID = $executionID;
$this->view->productInfo = $productInfo;
$this->view->productName = $this->products[$productID];
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0, $branch === 'all' ? 0 : $branch);
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0, ($branch === 'all' or !isset($branches[$branch])) ? 0 : $branch);
$this->view->currentModuleID = $currentModuleID;
$this->view->gobackLink = (isset($output['from']) and $output['from'] == 'global') ? $this->createLink('testcase', 'browse', "productID=$productID") : '';
$this->view->stories = $stories;
+17 -15
View File
@@ -70,25 +70,27 @@ $lang->testreport->bugStageList['generated'] = 'Generated Bugs';
$lang->testreport->bugStageList['legacy'] = 'Legacy Bugs';
$lang->testreport->bugStageList['resolved'] = 'Resolved Bugs';
$lang->testreport->caseSummary = 'Total <strong>%s</strong> cases. <strong>%s</strong> cases run. <strong>%s</strong> results generated. <strong>%s</strong> cases failed.';
$lang->testreport->buildSummary = 'Tested <strong>%s</strong> builds.';
$lang->testreport->confirmDelete = 'Do you want to delete this report?';
$lang->testreport->moreNotice = 'More features can be extended with reference to the ZenTao extension manual, or you can contact us at renee@easysoft.ltd for customization.';
$lang->testreport->exportNotice = "Exported By <a href='https://www.zentao.net' target='_blank' style='color:grey'>ZenTao</a>";
$lang->testreport->noReport = "No report has been generated. Please check it later.";
$lang->testreport->foundBugTip = "Bugs found in this build period and the affected build is in this test period.";
$lang->testreport->legacyBugTip = "Active bugs, or bugs that are not resolved in the test period.";
$lang->testreport->fromCaseBugTip = "Bugs found from the running of cases in the test period.";
$lang->testreport->errorTrunk = "You cannot create a Testing report for the trunk. Please modify the linked build!";
$lang->testreport->noTestTask = "No test requests for this {$lang->productCommon}, so no reports can be generated. Please go to {$lang->productCommon} which has test requests and then generate the report.";
$lang->testreport->noObjectID = "No test request or {$lang->executionCommon} is selected, so no report can be generated.";
$lang->testreport->moreProduct = "Testing reports can only be generated for the same {$lang->productCommon}.";
$lang->testreport->hiddenCase = "Hide %s use cases";
$lang->testreport->goalTip = "Descriptive information about the {$lang->execution->common} of this build";
$lang->testreport->caseSummary = 'Total <strong>%s</strong> cases. <strong>%s</strong> cases run. <strong>%s</strong> results generated. <strong>%s</strong> cases failed.';
$lang->testreport->buildSummary = 'Tested <strong>%s</strong> builds.';
$lang->testreport->confirmDelete = 'Do you want to delete this report?';
$lang->testreport->moreNotice = 'More features can be extended with reference to the ZenTao extension manual, or you can contact us at renee@easysoft.ltd for customization.';
$lang->testreport->exportNotice = "Exported By <a href='https://www.zentao.net' target='_blank' style='color:grey'>ZenTao</a>";
$lang->testreport->noReport = "No report has been generated. Please check it later.";
$lang->testreport->foundBugTip = "Bugs found in this build period and the affected build is in this test period.";
$lang->testreport->legacyBugTip = "Active bugs, or bugs that are not resolved in the test period.";
$lang->testreport->activatedBugTip = "Reactive bugs in the test period.";
$lang->testreport->fromCaseBugTip = "Bugs found from the running of cases in the test period.";
$lang->testreport->errorTrunk = "You cannot create a Testing report for the trunk. Please modify the linked build!";
$lang->testreport->noTestTask = "No test requests for this {$lang->productCommon}, so no reports can be generated. Please go to {$lang->productCommon} which has test requests and then generate the report.";
$lang->testreport->noObjectID = "No test request or {$lang->executionCommon} is selected, so no report can be generated.";
$lang->testreport->moreProduct = "Testing reports can only be generated for the same {$lang->productCommon}.";
$lang->testreport->hiddenCase = "Hide %s use cases";
$lang->testreport->goalTip = "Descriptive information about the {$lang->execution->common} of this build";
$lang->testreport->bugSummary = <<<EOD
Total <strong>%s</strong> Bugs reported <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->foundBugTip}'><i class='icon-help'></i></a>,
<strong>%s</strong> Bugs remained unresolved <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->legacyBugTip}'><i class='icon-help'></i></a>,
<strong>%s</strong> Bugs reactivated <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->activatedBugTip}'><i class='icon-help'></i></a>,
<strong>%s</strong> Bugs found from the running of cases<a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->fromCaseBugTip}'><i class='icon-help'></i></a>.
Bug Effective Rate <a data-toggle='tooltip' class='text-warning' title='Resolution is resolved or delayed / status is resolved or closed'><i class='icon-help'></i></a>: <strong>%s</strong>,Bugs-reported-from-cases rate<a data-toggle='tooltip' class='text-warning' title='Bugs created from cases / bugs'><i class='icon-help'></i></a>: <strong>%s</strong>
EOD;
+17 -15
View File
@@ -70,25 +70,27 @@ $lang->testreport->bugStageList['generated'] = '产生的Bug';
$lang->testreport->bugStageList['legacy'] = '遗留的Bug';
$lang->testreport->bugStageList['resolved'] = '解决的Bug';
$lang->testreport->caseSummary = '共有<strong>%s</strong>个用例,共执行<strong>%s</strong>个用例,产生了<strong>%s</strong>个结果,失败的用例有<strong>%s</strong>个。';
$lang->testreport->buildSummary = '共测试了<strong>%s</strong>个版本。';
$lang->testreport->confirmDelete = '是否删除该报告?';
$lang->testreport->moreNotice = '更多功能可以参考禅道扩展机制进行扩展,也可以联系我们进行定制。';
$lang->testreport->exportNotice = "由<a href='https://www.zentao.net' target='_blank' style='color:grey'>禅道项目管理软件</a>导出";
$lang->testreport->noReport = "暂无报告,请选择测试单生成测试报告。";
$lang->testreport->foundBugTip = "影响版本在测试轮次内,并且创建时间在测试时间范围内产生的Bug数。";
$lang->testreport->legacyBugTip = "Bug状态是激活,或Bug的解决时间在测试结束时间之后。";
$lang->testreport->fromCaseBugTip = "测试时间范围内,用例执行失败后创建的Bug。";
$lang->testreport->errorTrunk = "主干版本不能创建测试报告,请修改关联版本!";
$lang->testreport->noTestTask = "该{$lang->productCommon}下还没有关联非Trunk的测试单,不能创建报告。请先创建测试单,再创建。";
$lang->testreport->noObjectID = "没有选定测试单或{$lang->executionCommon},无法创建测试报告!";
$lang->testreport->moreProduct = "只能对同一个{$lang->productCommon}生成测试报告。";
$lang->testreport->hiddenCase = "隐藏 %s 个用例";
$lang->testreport->goalTip = "该版本所属{$lang->execution->common}的描述信息";
$lang->testreport->caseSummary = '共有<strong>%s</strong>个用例,共执行<strong>%s</strong>个用例,产生了<strong>%s</strong>个结果,失败的用例有<strong>%s</strong>个。';
$lang->testreport->buildSummary = '共测试了<strong>%s</strong>个版本。';
$lang->testreport->confirmDelete = '是否删除该报告?';
$lang->testreport->moreNotice = '更多功能可以参考禅道扩展机制进行扩展,也可以联系我们进行定制。';
$lang->testreport->exportNotice = "由<a href='https://www.zentao.net' target='_blank' style='color:grey'>禅道项目管理软件</a>导出";
$lang->testreport->noReport = "暂无报告,请选择测试单生成测试报告。";
$lang->testreport->foundBugTip = "影响版本在测试轮次内,并且创建时间在测试时间范围内产生的Bug数。";
$lang->testreport->legacyBugTip = "Bug状态是激活,或Bug的解决时间在测试结束时间之后。";
$lang->testreport->activatedBugTip = "在测试单时间范围内被激活的Bug数量。";
$lang->testreport->fromCaseBugTip = "测试时间范围内,用例执行失败后创建的Bug。";
$lang->testreport->errorTrunk = "主干版本不能创建测试报告,请修改关联版本!";
$lang->testreport->noTestTask = "该{$lang->productCommon}下还没有关联非Trunk的测试单,不能创建报告。请先创建测试单,再创建。";
$lang->testreport->noObjectID = "没有选定测试单或{$lang->executionCommon},无法创建测试报告!";
$lang->testreport->moreProduct = "只能对同一个{$lang->productCommon}生成测试报告。";
$lang->testreport->hiddenCase = "隐藏 %s 个用例";
$lang->testreport->goalTip = "该版本所属{$lang->execution->common}的描述信息";
$lang->testreport->bugSummary = <<<EOD
共发现<strong>%s</strong>个Bug <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->foundBugTip}'><i class='icon-help'></i></a>,
遗留<strong>%s</strong>个Bug <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->legacyBugTip}'><i class='icon-help'></i></a>。
重新激活<strong>%s</strong>个Bug <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->activatedBugTip}'><i class='icon-help'></i></a>。
用例执行产生<strong>%s</strong>个Bug <a data-toggle='tooltip' class='text-warning' title='{$lang->testreport->fromCaseBugTip}'><i class='icon-help'></i></a>。
有效Bug率(方案为已解决或延期 / 状态为已解决或已关闭):<strong>%s</strong>,用例发现Bug率(用例创建的Bug / 发现Bug数):<strong>%s</strong>
EOD;
+45
View File
@@ -141,6 +141,7 @@ class testreportModel extends model
$resolvedBugs = $this->dao->select('*')->from(TABLE_BUG)->where('product')->in($productIdList)->andWhere('resolvedDate')->ge($begin)->andWhere('resolvedDate')->le("$end 23:59:59")->andWhere('deleted')->eq(0)->fetchAll();
$foundBugs = array();
$legacyBugs = array();
$activatedBugs = array();
$byCaseNum = 0;
$buildIdList = array_keys($builds);
$taskIdList = array_keys($tasks);
@@ -168,6 +169,48 @@ class testreportModel extends model
$handleGroups['resolved'][$date] = 0;
}
$buildBugs = array();
$allBugs = $this->dao->select('*')->from(TABLE_BUG)->where('product')->in($productIdList)->andWhere('deleted')->eq(0)->fetchAll('id');
foreach($allBugs as $bug)
{
if(!empty(array_intersect(explode(',', $bug->openedBuild), $buildIdList))) $buildBugs[$bug->id] = $bug;
}
/* Get bug reactivated actions during the testreport. */
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->eq('bug')
->andWhere('action')->eq('activated')
->andWhere('date')->ge($begin)
->andWhere('date')->le($end . ' 23:59:59')
->andWhere('objectID')->in(array_keys($buildBugs))
->fetchGroup('objectID', 'id');
$actionIdList = array();
foreach($actions as $bugID => $action) $actionIdList = array_merge($actionIdList, array_keys($action));
$histories = $this->loadModel('action')->getHistory($actionIdList);
foreach($actions as $bugID => $actionList)
{
foreach($actionList as $actionID => $action)
{
$action->history = zget($histories, $actionID, array());
}
}
foreach($buildBugs as $bug)
{
$bugActions = zget($actions, $bug->id, array());
foreach($bugActions as $action)
{
foreach($action->history as $history)
{
if($history->field == 'openedBuild' and !in_array($history->new, $buildIdList)) continue;
$activatedBugs[$bug->id] = $bug;
}
}
}
/* Get the resolved bug data. */
foreach($resolvedBugs as $bug)
{
@@ -216,6 +259,7 @@ class testreportModel extends model
}
$resolvedBugs = 0;
$this->loadModel('action');
foreach($foundBugs as $bug)
{
$severityGroups[$bug->severity] = isset($severityGroups[$bug->severity]) ? $severityGroups[$bug->severity] + 1 : 1;
@@ -231,6 +275,7 @@ class testreportModel extends model
$bugInfo['foundBugs'] = count($foundBugs);
$bugInfo['legacyBugs'] = $legacyBugs;
$bugInfo['activatedBugs'] = $activatedBugs;
$bugInfo['countBugByTask'] = $byCaseNum;
$bugInfo['bugConfirmedRate'] = empty($resolvedBugs) ? 0 : round((zget($resolutionGroups, 'fixed', 0) + zget($resolutionGroups, 'postponed', 0)) / $resolvedBugs * 100, 2);
$bugInfo['bugCreateByCaseRate'] = empty($byCaseNum) ? 0 : round($byCaseNum / count($foundBugs) * 100, 2);
+2 -2
View File
@@ -83,8 +83,8 @@
<?php
echo '<div>' . $storySummary . '</div>';
echo '<div>' . sprintf($lang->testreport->buildSummary, empty($builds) ? 1 : count($builds)) . $caseSummary . '</div>';
echo '<div>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</div>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']);
echo '<div>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), count($bugInfo['activatedBugs']), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</div>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']); unset($bugInfo['activatedBugs']);
?>
</td>
<td></td>
+2 -2
View File
@@ -71,8 +71,8 @@
<?php
echo '<p>' . $storySummary . '</p>';
echo '<p>' . sprintf($lang->testreport->buildSummary, empty($builds) ? 1 : count($builds)) . $caseSummary . '</p>';
echo '<p>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</p>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']);
echo '<p>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), count($bugInfo['activatedBugs']), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</p>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']); unset($bugInfo['activatedBugs']);
?>
</td>
<td></td>
+2 -2
View File
@@ -78,8 +78,8 @@
<?php
echo '<p>' . $storySummary . '</p>';
echo '<p>' . sprintf($lang->testreport->buildSummary, empty($builds) ? 1 : count($builds)) . $caseSummary . '</p>';
echo '<p>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</p>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']);
echo '<p>' . sprintf($lang->testreport->bugSummary, $bugInfo['foundBugs'], count($legacyBugs), count($bugInfo['activatedBugs']), $bugInfo['countBugByTask'], $bugInfo['bugConfirmedRate'] . '%', $bugInfo['bugCreateByCaseRate'] . '%') . '</p>';
unset($bugInfo['countBugByTask']); unset($bugInfo['bugConfirmedRate']); unset($bugInfo['bugCreateByCaseRate']); unset($bugInfo['foundBugs']); unset($bugInfo['activatedBugs']);
?>
</td>
</tr>
+2 -2
View File
@@ -71,7 +71,7 @@ class testsuite extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$suites = $this->testsuite->getSuites($productID, $sort, $pager);
if(empty($suites) and $pageID > 1)
@@ -169,7 +169,7 @@ class testsuite extends control
$this->session->set('caseList', $this->app->getURI(true), 'qa');
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
+5 -3
View File
@@ -106,7 +106,7 @@ class testtask extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Get tasks. */
$tasks = $this->testtask->getProductTasks($productID, $branch, $sort, $pager, $scopeAndStatus, $beginTime, $endTime);
@@ -178,7 +178,7 @@ class testtask extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->common;
$this->view->position[] = html::a($this->createLink('testtask', 'browseUnits', "productID=$productID"), $this->products[$productID]);
@@ -503,7 +503,7 @@ class testtask extends control
}
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy, 't2.id');
$sort = common::appendOrder($orderBy, 't2.id');
/* Get test cases. */
$runs = $this->testtask->getTaskCases($productID, $browseType, $queryID, $moduleID, $sort, $pager, $task);
@@ -1314,6 +1314,8 @@ class testtask extends control
*/
public function results($runID, $caseID = 0, $version = 0)
{
if($this->app->tab == 'project') $this->loadModel('project')->setMenu($this->session->project);
if($runID)
{
$case = $this->testtask->getRunById($runID)->case;
+1 -1
View File
@@ -120,7 +120,7 @@
<?php endif; endif; $childId++;?>
</tr>
<?php endforeach;?>
<?php if($result->caseResult == 'fail'):?>
<?php if($result->caseResult == 'fail' and common::hasPriv('testcase', 'createBug')):?>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td>
<td><?php echo html::commonButton($lang->testcase->createBug, "onclick='createBug(this)'", "btn btn-primary createBtn");?></td>
+3 -1
View File
@@ -243,7 +243,7 @@ class treeModel extends model
{
/* If createdVersion <= 4.1, go to getOptionMenu(). */
$products = $this->loadModel('product')->getProductPairsByProject($rootID);
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed');
if(!$this->isMergeModule($rootID, 'task') or !$products) return $this->getOptionMenu($rootID, 'task', $startModule);
@@ -277,10 +277,12 @@ class treeModel extends model
{
foreach($rootModules as $id => $rootModule)
{
$activeBranch = isset($branchGroups[$id]) ? array_keys($branchGroups[$id]) : array();
if($type == 'product')
{
$modules = $this->dao->select('*')->from(TABLE_MODULE)->where("((root = '" . (int)$rootID . "' and type = 'task' and parent != 0) OR (root = $id and type = 'story'))")
->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
->beginIF(!empty($activeBranch))->andWhere('branch')->in($activeBranch)->fi()
->andWhere('deleted')->eq(0)
->orderBy('grade desc, branch, `order`, type')
->fetchAll('id');
+22 -6
View File
@@ -395,7 +395,7 @@ class upgrade extends control
$data->project = $_POST['projectType'] == 'execution' ? $projectList : $projectList[$projectProduct->project];
$data->product = $projectProduct->product;
$data->plan = $projectProduct->plan;
$data->branch = $projectProduct->branch;
$data->branch = $projectProduct->branch;
$this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec();
}
@@ -406,7 +406,7 @@ class upgrade extends control
/* Get no merged product and project count. */
$noMergedProductCount = $this->dao->select('count(*) as count')->from(TABLE_PRODUCT)->where('program')->eq(0)->fetch('count');
$noMergedSprintCount = $this->dao->select('count(*) as count')->from(TABLE_PROJECT)->where('grade')->eq(0)->andWhere('path')->eq('')->andWhere('type')->ne('program')->fetch('count');
$noMergedSprintCount = $this->dao->select('count(*) as count')->from(TABLE_PROJECT)->where('grade')->eq(0)->andWhere('path')->eq('')->andWhere('type')->ne('program')->andWhere('deleted')->eq(0)->fetch('count');
/* When all products and projects merged then finish and locate afterExec page. */
if(empty($noMergedProductCount) and empty($noMergedSprintCount))
@@ -443,6 +443,7 @@ class upgrade extends control
$noMergedSprints = $this->dao->select('t1.*')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id=t2.project')
->where('t1.project')->eq(0)
->andWhere('t1.deleted')->eq(0)
->andWhere('t1.type')->eq('sprint')
->andWhere('t2.product')->in(array_keys($noMergedProducts))
->orderBy('t1.id_desc')
@@ -487,6 +488,7 @@ class upgrade extends control
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t2.model')->eq('')
->andWhere('t2.project')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.type')->eq('sprint')
->fetchAll('id');
@@ -531,7 +533,13 @@ class upgrade extends control
/* Get no merged projects than is not linked product. */
if($type == 'sprint')
{
$noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)->where('parent')->eq(0)->andWhere('path')->eq('')->orderBy('id_desc')->fetchAll('id');
$noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)
->where('parent')->eq(0)
->andWhere('path')->eq('')
->andWhere('deleted')->eq(0)
->orderBy('id_desc')
->fetchAll('id');
$projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
foreach($projectProducts as $sprintID => $products) unset($noMergedSprints[$sprintID]);
@@ -543,8 +551,16 @@ class upgrade extends control
/* Get no merged projects that link more then two products. */
if($type == 'moreLink')
{
$noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)->where('parent')->eq(0)->andWhere('path')->eq('')->orderBy('id_desc')->fetchAll('id');
$projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
$noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)
->where('parent')->eq(0)
->andWhere('path')->eq('')
->andWhere('deleted')->eq(0)
->orderBy('id_desc')
->fetchAll('id');
$projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)
->where('project')->in(array_keys($noMergedSprints))
->fetchGroup('project', 'product');
$productPairs = array();
foreach($projectProducts as $sprintID => $products)
@@ -591,7 +607,7 @@ class upgrade extends control
* Rename object in upgrade.
*
* @param string $type project|product|execution
* @param string $duplicateList
* @param string $duplicateList
* @access public
* @return void
*/
+2
View File
@@ -0,0 +1,2 @@
#selectedModeTips {padding-top: 10px}
#upgradeTips {padding-bottom: 10px;}
+1
View File
@@ -126,6 +126,7 @@ $lang->upgrade->mergeRepoTips = "Merge the selected version library under t
$lang->upgrade->needBuild4Add = 'Full text retrieval has been added in this upgrade. Need create index. Please go [Admin->System->BuildIndex] page to build index.';
$lang->upgrade->errorEngineInnodb = 'Your MySQL does not support InnoDB data table engine. Please modify it to MyISAM and try again.';
$lang->upgrade->duplicateProject = "Project name in the same program cannot be duplicate. Please adjust the duplicate names.";
$lang->upgrade->upgradeTips = "Historically deleted data cannot be upgraded, and restoration is not supported after the upgrade. Please be aware.";
$lang->upgrade->projectType['project'] = "Upgrade the historical {$lang->projectCommon} as a project";
$lang->upgrade->projectType['execution'] = "Upgrade the historical {$lang->projectCommon} as an execution";
+1
View File
@@ -126,6 +126,7 @@ $lang->upgrade->mergeRepoTips = "将选中的版本库归并到所选产品
$lang->upgrade->needBuild4Add = '本次升级需要创建索引。请到 [后台->系统->重建索引] 页面,重新创建索引。';
$lang->upgrade->errorEngineInnodb = '您当前的数据库不支持使用InnoDB数据表引擎,请修改为MyISAM后重试。';
$lang->upgrade->duplicateProject = "同一个项目集内项目名称不能重复,请调整重名的项目名称";
$lang->upgrade->upgradeTips = "历史删除数据不参与升级,升级后将不支持还原,请知悉";
$lang->upgrade->projectType['project'] = "把历史的{$lang->projectCommon}作为项目升级";
$lang->upgrade->projectType['execution'] = "把历史的{$lang->projectCommon}作为执行升级";
+2 -1
View File
@@ -39,12 +39,12 @@
<?php echo $lang->upgrade->to15Desc;?>
<?php $systemMode = isset($lang->upgrade->to15Mode['classic']) ? 'classic' : 'new';?>
<?php echo html::radio('mode', $lang->upgrade->to15Mode, $systemMode);?>
<p> </p>
<div id='selectedModeTips' class='text-info'><?php echo $lang->upgrade->selectedModeTips[$systemMode];?></div>
</div>
</div>
<hr/>
<div class='panel-footer text-center'>
<div id='upgradeTips' class='text-danger hidden'><?php echo $lang->upgrade->upgradeTips;?></div>
<?php echo html::submitButton($lang->upgrade->start . (strpos($this->app->getClientLang(), 'zh') === false ? ' ' : '') . $lang->upgrade->common);?>
</div>
</form>
@@ -57,6 +57,7 @@ $(function()
$('[name=mode]').change(function()
{
$('#selectedModeTips').html(selectedModeTips[$(this).val()]);
$(this).val() == 'new' ? $('#upgradeTips').removeClass('hidden') : $('#upgradeTips').addClass('hidden');
})
})
</script>
+9 -8
View File
@@ -74,7 +74,7 @@ class user extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
/* Get user, totos. */
$account = $user->account;
@@ -259,7 +259,7 @@ class user extends control
$this->app->loadLang('testcase');
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$this->view->title = $this->lang->user->common . $this->lang->colon . $this->lang->user->testTask;
$this->view->position[] = $this->lang->user->testTask;
@@ -301,7 +301,7 @@ class user extends control
$users = $this->loadModel('dept')->getDeptUserPairs($this->app->user->dept, 'id');
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$cases = array();
if($type == 'case2Him')
@@ -1097,7 +1097,7 @@ class user extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$sort = common::appendOrder($orderBy);
$date = empty($date) ? '' : date('Y-m-d', $date);
$actions = $this->loadModel('action')->getDynamic($account, $period, $sort, $pager, 'all', 'all', 'all', $date, $direction);
@@ -1165,19 +1165,20 @@ class user extends control
* AJAX: get users from a contact list.
*
* @param int $contactListID
* @param string $dropdownName
* @access public
* @return string
*/
public function ajaxGetContactUsers($contactListID)
public function ajaxGetContactUsers($contactListID, $dropdownName = 'mailto')
{
$list = $contactListID ? $this->user->getContactListByID($contactListID) : '';
$users = $this->user->getPairs('devfirst|nodeleted', $list ? $list->userList : '', $this->config->maxCount);
if(isset($this->config->user->moreLink)) $this->config->moreLinks['mailto[]'] = $this->config->user->moreLink;
if(isset($this->config->user->moreLink)) $this->config->moreLinks[$dropdownName . "[]"] = $this->config->user->moreLink;
if(!$contactListID) return print(html::select('mailto[]', $users, '', "class='form-control chosen' multiple data-placeholder='{$this->lang->chooseUsersToMail}'"));
if(!$contactListID) return print(html::select($dropdownName . "[]", $users, '', "class='form-control chosen' multiple data-placeholder='{$this->lang->chooseUsersToMail}'"));
return print(html::select('mailto[]', $users, $list->userList, "class='form-control chosen' multiple data-placeholder='{$this->lang->chooseUsersToMail}'"));
return print(html::select($dropdownName . "[]", $users, $list->userList, "class='form-control chosen' multiple data-placeholder='{$this->lang->chooseUsersToMail}'"));
}
/**
+33
View File
@@ -205,6 +205,39 @@ class userModel extends model
return $users;
}
/**
* Get users info list for displaying
*
* @param array $accounts
* @param int $deptID
* @param string $type
* @access public
* @return array
*/
public function getUserDisplayInfos($accounts, $deptID = 0, $type = 'inside')
{
$users = $this->dao->select('account, realname, avatar, dept, role')->from(TABLE_USER)
->where('deleted')->eq(0)
->beginIF($accounts)->andWhere('type')->eq($type)->fi()
->beginIF($accounts)->andWhere('account')->in($accounts)->fi()
->fetchAll('account');
$depts = $this->loadModel('dept')->getDeptPairs($deptID);
$infos = array();
foreach($users as $info)
{
$info->roleName = zget($this->lang->user->roleList, $info->role, '');
if(isset($depts[$info->dept])) $info->deptName = $depts[$info->dept];
if(empty($info->avatar)) unset($info->avatar);
if(empty($info->realname)) unset($info->realname);
if(empty($info->role)) unset($info->role);
if(empty($info->roleName)) unset($info->roleName);
$infos[$info->account] = $info;
}
return $infos;
}
/**
* Get user info by ID.
*
-2
View File
@@ -16,7 +16,6 @@ $jsFiles[] = $jqueryRoot . 'lib.js';
$jsFiles[] = $jqueryRoot . 'tablesorter/min.js';
$jsFiles[] = $jqueryRoot . 'tablesorter/metadata.js';
$jsFiles[] = $jsRoot . 'zui/min.js';
$jsFiles[] = $jsRoot . 'zui/picker/zui.picker.min.js';
$jsFiles[] = $jsRoot . 'my.full.js';
/* Combine these js files. */
@@ -58,7 +57,6 @@ $themes = array_keys($lang->themes);
/* Create css files for every them and every lang. */
$zuiCode = str_replace(array('/*!', '../fonts'), array('/*', '../zui/fonts'), file_get_contents($themeRoot . 'zui/css/min.css'));
$zuiCode .= "\n" . str_replace('/*!', '/*', file_get_contents($jsRoot . 'zui/picker/zui.picker.min.css')) . "\n";
foreach($langs as $lang)
{
foreach($themes as $theme)
+1 -1
View File
@@ -136,7 +136,7 @@ function showMoreImage(obj)
*/
function setMailto(mailto, contactListID)
{
link = createLink('user', 'ajaxGetContactUsers', 'listID=' + contactListID);
link = createLink('user', 'ajaxGetContactUsers', 'listID=' + contactListID + '&dropdownName=' + mailto);
$.get(link, function(users)
{
$('#' + mailto).replaceWith(users);
+16 -15
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long