Merge branch 'sprint/185' into 'sprint/185_zhangzilong_49284'

# Conflicts:
#   db/update16.4.sql
This commit is contained in:
孙广明
2022-02-18 06:23:22 +00:00
74 changed files with 1098 additions and 208 deletions
+1
View File
@@ -1701,6 +1701,7 @@ class block extends control
*/
public function printAssignToMeBlock($longBlock = true)
{
$hasViewPriv = array();
if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true;
if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true;
if(common::hasPriv('bug', 'view')) $hasViewPriv['bug'] = true;
+1
View File
@@ -99,6 +99,7 @@ $lang->block->productName = $lang->productCommon . ' Name';
$lang->block->totalStory = 'The Total ' . $lang->SRCommon;
$lang->block->totalBug = 'The Total Bug';
$lang->block->totalRelease = 'Release The Number';
$lang->block->totalTask = 'The Total ' . $lang->task->common;
$lang->block->totalInvestment = 'Total investment';
$lang->block->totalPeople = 'Total number';
+1
View File
@@ -99,6 +99,7 @@ $lang->block->productName = $lang->productCommon . '名称';
$lang->block->totalStory = '总' . $lang->SRCommon;
$lang->block->totalBug = '总Bug';
$lang->block->totalRelease = '发布次数';
$lang->block->totalTask = '总' . $lang->task->common;
$lang->block->totalInvestment = '总投入';
$lang->block->totalPeople = '总人数';
+11 -6
View File
@@ -10,6 +10,7 @@
* @link http://www.zentao.net
*/
?>
<?php $vision = $this->config->vision;?>
<?php if(empty($totalData)): ?>
<div class='empty-tip'><?php common::printLink('project', 'create', '', "<i class='icon-plus'></i> " . $lang->project->create, '', "class='btn btn-primary'")?></div>
<?php else:?>
@@ -22,7 +23,11 @@
<th></th>
<th><?php echo $lang->workingHour;?></th>
<th></th>
<?php if($vision == 'lite'): ?>
<th><?php echo $lang->block->taskCount;?></th>
<?php else:?>
<th><?php echo $lang->block->bugCount;?></th>
<?php endif;?>
<th></th>
</tr>
</thead>
@@ -34,8 +39,8 @@
<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>
<td><?php echo $totalData[$projectID]->allBugs;?></td>
<th><?php echo ($vision == 'lite' ? $lang->block->totalTask : $lang->block->totalBug) . ':';?></th>
<td><?php echo $vision == 'lite' ? $totalData[$projectID]->allTasks : $totalData[$projectID]->allBugs;?></td>
</tr>
<tr>
<th><?php echo $lang->block->done . ':';?></th>
@@ -44,8 +49,8 @@
<td></td>
<th><?php echo $lang->block->consumedHours . ':';?></th>
<td><?php echo $totalData[$projectID]->consumed . $lang->execution->workHour;?></td>
<th><?php echo $lang->bug->statusList['resolved'] . ':';?></th>
<td><?php echo $totalData[$projectID]->doneBugs;?></td>
<th><?php echo ($vision == 'lite' ? $lang->block->done : $lang->bug->statusList['resolved']) . ':';?></th>
<td><?php echo $vision == 'lite' ? $totalData[$projectID]->doneTasks : $totalData[$projectID]->doneBugs;?></td>
</tr>
<tr>
<th><?php echo $lang->block->left . ':';?></th>
@@ -54,8 +59,8 @@
<td></td>
<th></th>
<td></td>
<th><?php echo $lang->bug->unResolved . ':';?></th>
<td><?php echo $totalData[$projectID]->leftBugs;?></td>
<th><?php echo ($vision == 'lite' ? $lang->block->undone : $lang->bug->unResolved) . ':';?></th>
<td><?php echo $vision == 'lite' ? $totalData[$projectID]->leftTasks : $totalData[$projectID]->leftBugs;?></td>
</tr>
</tbody>
+4 -4
View File
@@ -999,7 +999,7 @@ class bug extends control
$this->view->branchTagOption = $branchTagOption;
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
$this->view->users = $this->user->getPairs('noclosed', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->openedBuilds = $openedBuilds;
$this->view->resolvedBuilds = array('' => '') + $openedBuilds + $oldResolvedBuild;
$this->view->actions = $this->action->getList('bug', $bugID);
@@ -1135,7 +1135,7 @@ class bug extends control
$appendUsers[$bug->assignedTo] = $bug->assignedTo;
$appendUsers[$bug->resolvedBy] = $bug->resolvedBy;
}
$users = $this->user->getPairs('devfirst|noclosed', $appendUsers, $this->config->maxCount);
$users = $this->user->getPairs('devfirst', $appendUsers, $this->config->maxCount);
$users = array('' => '', 'ditto' => $this->lang->bug->ditto) + $users;
/* Assign. */
@@ -1709,8 +1709,8 @@ class bug extends control
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->recTotal = $recTotal;
$this->view->recPerPage = $recPerPage;
$this->view->pageID = $pageID;
$this->view->recPerPage = $recPerPage;
$this->view->pageID = $pageID;
$this->display();
}
+2 -1
View File
@@ -1357,10 +1357,11 @@ class bugModel extends model
* @param int $bugID
* @param string $browseType
* @param int $queryID
* @param object $pager
* @access public
* @return array
*/
public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager)
public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager = null)
{
if($browseType == 'bySearch')
{
+1 -1
View File
@@ -320,7 +320,7 @@ $lang->exportTypeList['all'] = '全部记录';
$lang->exportTypeList['selected'] = '选中记录';
$lang->visionList = array();
$lang->visionList['rnd'] = '研发界面';
$lang->visionList['rnd'] = '研发综合界面';
$lang->visionList['lite'] = '迅捷界面';
$lang->createObjects['todo'] = '待办';
+40 -12
View File
@@ -393,9 +393,6 @@ class commonModel extends model
{
$isGuest = $app->user->account == 'guest';
echo "<a class='dropdown-toggle' data-toggle='dropdown'>";
echo html::avatar($app->user);
echo '</a>';
echo "<ul class='dropdown-menu pull-right'>";
if(!$isGuest)
{
@@ -406,11 +403,6 @@ class commonModel extends model
echo '<div class="user-profile-name">' . (empty($app->user->realname) ? $app->user->account : $app->user->realname) . '</div>';
if(isset($lang->user->roleList[$app->user->role])) echo '<div class="user-profile-role">' . $lang->user->roleList[$app->user->role] . '</div>';
echo '</a></li><li class="divider"></li>';
$vision = $app->config->vision == 'lite' ? 'rnd' : 'lite';
echo '<li>' . html::a(helper::createLink('my', 'ajaxSwitchVision', "vision=$vision"), "<i class='icon icon-exchange'></i> " . sprintf($lang->user->switchVision, $lang->visionList[$vision]), '', "data-type='ajax'") . '</li>';
echo '<li class="divider"></li>';
echo '<li>' . html::a(helper::createLink('my', 'profile', '', '', true), "<i class='icon icon-account'></i> " . $lang->profile, '', "class='iframe' data-width='600'") . '</li>';
if($app->config->vision === 'rnd')
@@ -462,6 +454,38 @@ class commonModel extends model
echo html::a(helper::createLink('user', 'logout'), "<i class='icon icon-exit'></i> " . $lang->logout, '_top');
}
echo '</li></ul>';
echo "<a class='dropdown-toggle' data-toggle='dropdown'>";
echo html::avatar($app->user);
echo '</a>';
}
}
/**
* Print vision switcher.
*
* @static
* @access public
* @return void
*/
public static function printVisionSwitcher()
{
global $lang, $app;
if(isset($app->user))
{
$vision = $app->config->vision;
echo "<ul class='dropdown-menu pull-right'>";
foreach($lang->visionList as $visionKey => $visionName)
{
echo ($vision == $visionKey ? '<li class="active">' : '<li>') . html::a(helper::createLink('my', 'ajaxSwitchVision', "vision=$visionKey"), $visionName, '', "data-type='ajax'") . '</li>';
}
echo '</ul>';
echo "<a class='dropdown-toggle' data-toggle='dropdown'>";
echo "<div>{$lang->visionList[$vision]}</div>";
echo '</a>';
}
}
@@ -476,9 +500,7 @@ class commonModel extends model
{
global $app, $config, $lang;
$html = "<a class='dropdown-toggle' data-toggle='dropdown'>";
$html .= "<i class='icon icon-plus-solid-circle text-secondary'></i>";
$html .= "</a><ul class='dropdown-menu pull-right create-list'>";
$html = "<ul class='dropdown-menu pull-right create-list'>";
/* Initialize the default values. */
$showCreateList = $needPrintDivider = false;
@@ -600,6 +622,10 @@ class commonModel extends model
if(!$showCreateList) return '';
$html .= "</ul>";
$html .= "<a class='dropdown-toggle' data-toggle='dropdown'>";
$html .= "<i class='icon icon-plus-solid-circle text-secondary'></i>";
$html .= "</a>";
echo $html;
}
@@ -2225,7 +2251,9 @@ EOD;
/* Reset priv by program privway. */
$rights = $this->app->user->rights['rights'];
$this->app->user = clone $_SESSION['user'];
$this->app->user = clone $_SESSION['user'];
if($this->app->user->account == $program->openedBy or $this->app->user->account == $program->PM) $program->auth = 'extend';
if($program->auth == 'extend') $this->app->user->rights['rights'] = array_merge_recursive($programRightGroup, $rights);
if($program->auth == 'reset')
+2 -1
View File
@@ -19,8 +19,9 @@ include 'chosen.html.php';
<div id='toolbar'>
<div id='userMenu'>
<ul id="userNav" class="nav nav-default">
<li class='dropdown dropdown-hover has-avatar'><?php common::printUserBar();?></li>
<li class='dropdown dropdown-hover' id='globalCreate'><?php common::printCreateList();?></li>
<li class='dropdown dropdown-hover has-avatar'><?php common::printUserBar();?></li>
<li class='dropdown dropdown-hover' id='visionSwitcher'><?php common::printVisionSwitcher();?></li>
</ul>
</div>
</div>
+23 -1
View File
@@ -1037,12 +1037,34 @@ function processMinusBtn()
}
}
/**
* Create task menu
* @returns {Object[]}
*/
function createTaskMenu(options)
{
var $card = options.$trigger.closest('.kanban-item');
var task = $card.data('item');
var items = [];
$.each(task.menus, function()
{
var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}};
if(this.size) item.attrs['data-width'] = this.size;
items.push(item);
});
return items;
}
/* Define menu creators */
window.menuCreators =
{
lane: createLaneMenu,
column: createColumnMenu,
columnCreate: createColumnCreateMenu
columnCreate: createColumnCreateMenu,
task: createTaskMenu,
};
/**
+1
View File
@@ -115,6 +115,7 @@
return link.prj ? 'project' : 'report';
}
}
if(moduleName === 'story' && vision === 'lite') return 'project'
if(moduleName === 'story' && methodLowerCase === 'zerocase')
{
return link.params.from == 'project' ? 'project' : 'qa';
+1
View File
@@ -517,6 +517,7 @@ class installModel extends model
$admin->realname = $this->post->account;
$admin->password = md5($this->post->password);
$admin->gender = 'f';
$admin->visions = 'rnd,lite';
$this->dao->replace(TABLE_USER)->data($admin)->check('account', 'notempty')->exec();
}
}
+20 -37
View File
@@ -1675,52 +1675,35 @@ class kanbanModel extends model
->fetchAll('id');
if($this->app->user->admin) return array_keys($objects);
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,type,team,whitelist')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,type')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
if($this->app->user->admin and $param != 'involved') return array_keys($objects);
$account = $this->app->user->account;
foreach($objects as $objectID => $object)
{
if(!$this->checkKanbanPriv($object, $objectType, $spaceList)) unset($objects[$objectID]);
$remove = true;
if($objectType == 'kanbanspace' and $object->type == 'public' and $param != 'involved') continue;
if($object->owner == $account and $param != 'involved') $remove = false;
if(strpos(",{$object->team},", ",$account,") !== false) $remove = false;
if(strpos(",{$object->whitelist},", ",$account,") !== false) $remove = false;
if($objectType == 'kanban')
{
$spaceOwner = isset($spaceList[$object->space]->owner) ? $spaceList[$object->space]->owner : '';
$spaceType = isset($spaceList[$object->space]->type) ? $spaceList[$object->space]->type : '';
if(strpos(",$spaceOwner,", ",$account,") !== false) $remove = false;
if($spaceType == 'public' and $param != 'involved') $remove = false;
}
if($objectType == 'kanbanspace' and $param == 'involved' and $object->owner == $account) $remove = true;
if($remove) unset($objects[$objectID]);
}
return array_keys($objects);
}
/**
* Check kanban priv.
*
* @param object $object
* @param string $objectType
* @param array $spaceList
* @access public
* @return bool
*/
public function checkKanbanPriv($object, $objectType, $spaceList)
{
$account = $this->app->user->account;
if($object->acl == 'private' or $object->acl == 'extend')
{
if($objectType == 'kanbanspace' and $object->type == 'public' and $param != 'involved') return true;
if($object->owner == $account and $param != 'involved') return true;
if(strpos(",{$object->team},", ",$account,") !== false) return true;
if(strpos(",{$object->whitelist},", ",$account,") !== false) return true;
if($objectType == 'kanban')
{
$spaceOwner = isset($spaceList[$object->space]->owner) ? $spaceList[$object->space]->owner : '';
$spaceTeam = isset($spaceList[$object->space]->team) ? trim($spaceList[$object->space]->team, ',') : '';
$spaceWhiteList = isset($spaceList[$object->space]->whitelist) ? trim($spaceList[$object->space]->whitelist, ',') : '';
if(strpos(",$spaceOwner,", ",$account,") !== false) return true;
if(strpos(",$spaceTeam,", ",$account,") !== false and $object->acl == 'extend') return true;
if(strpos(",$spaceWhiteList,", ",$account,") !== false and $object->acl == 'extend') return true;
if($spaceType == 'public' and $param != 'involved') return true;
}
return false;
}
return true;
}
/**
* Create a space.
*
+4
View File
@@ -1273,6 +1273,10 @@ EOF;
{
$_SESSION['vision'] = $vision;
$this->loadModel('setting')->setItem("{$this->app->user->account}.common.global.vision", $vision);
$this->config->vision = $vision;
$_SESSION['user']->rights = $this->loadModel('user')->authorize($this->app->user->account);
echo js::locate($this->createLink('my', 'index'), 'parent');
}
}
+7 -1
View File
@@ -18,7 +18,7 @@
<h2><i class='icon-pencil'></i> <?php echo $lang->my->editProfile;?></h2>
</div>
<form method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<table class='table table-form'>
<caption><?php echo $lang->my->form->lblBasic;?></caption>
<tr>
<th class='w-90px'><?php echo $lang->user->realname;?></th>
@@ -83,12 +83,18 @@
</td>
</tr>
</table>
<?php echo html::select('visions[]', $this->user->getVisionList(), $user->visions, "class='form-control chosen' multiple");?>
<div class='text-center form-actions'><?php echo html::submitButton() . html::backButton();?></div>
</form>
<?php echo html::hidden('verifyRand', $rand);?>
</div>
<?php js::set('passwordStrengthList', $lang->user->passwordStrengthList)?>
<script>
$(function()
{
$('#visions_chosen').css('display', 'none')
});
function checkPassword(password)
{
$('#passwordStrength').html(password == '' ? '' : passwordStrengthList[computePasswordStrength(password)]);
+1
View File
@@ -133,6 +133,7 @@ class programModel extends model
return $this->dao->select('*')->from(TABLE_PROGRAM)
->where('type')->in('program,project')
->andWhere('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
->beginIF(!$this->app->user->admin)
->andWhere('(id')->in($this->app->user->view->programs)
->orWhere('id')->in($this->app->user->view->projects)
+28 -2
View File
@@ -310,6 +310,10 @@ class projectModel extends model
$allBugs = $this->getTotalBugByProject($projectIdList, 'all');
$doneBugs = $this->getTotalBugByProject($projectIdList, 'resolved');
$leftTasks = $this->getTotalTaskByProject($projectIdList, 'undone');
$allTasks = $this->getTotalTaskByProject($projectIdList, 'all');
$doneTasks = $this->getTotalTaskByProject($projectIdList, 'done');
foreach($projects as $projectID => $project)
{
$project->consumed = isset($hours[$projectID]) ? (float)$hours[$projectID]->consumed : 0;
@@ -322,6 +326,9 @@ class projectModel extends model
$project->allStories = $allStories[$projectID];
$project->doneStories = $doneStories[$projectID];
$project->leftStories = $leftStories[$projectID];
$project->leftTasks = isset($leftTasks[$projectID]) ? $leftTasks[$projectID] : 0;
$project->allTasks = isset($allTasks[$projectID]) ? $allTasks[$projectID] : 0;
$project->doneTasks = isset($doneTasks[$projectID]) ? $doneTasks[$projectID] : 0;
if(is_float($project->consumed)) $project->consumed = round($project->consumed, 1);
if(is_float($project->estimate)) $project->estimate = round($project->estimate, 1);
@@ -553,6 +560,25 @@ class projectModel extends model
->fetchPairs('project');
}
/**
* Get associated tasks by project.
*
* @param array $projectIdList
* @param string $status all|done|undone
* @access public
* @return array
*/
public function getTotalTaskByProject($projectIdList, $status)
{
return $this->dao->select('project, count(*) as tasks')->from(TABLE_TASK)
->where('project')->in($projectIdList)
->andWhere('deleted')->eq(0)
->beginIF($status == 'done')->andWhere('status')->in('done,closed')->fi()
->beginIF($status == 'undone')->andWhere('status')->in('wait,pause,cancel')->fi()
->groupBy('project')
->fetchPairs('project');
}
/**
* Get branches by project id.
*
@@ -917,7 +943,7 @@ class projectModel extends model
$lib->main = '1';
$lib->acl = $project->acl != 'program' ? $project->acl : 'custom';
$lib->users = ',' . implode(',', array_filter($authorizedUsers)) . ',';
$lib->vision = zget($project, 'vision', 'common');
$lib->vision = zget($project, 'vision', 'rnd');
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
$this->updateProducts($projectID);
@@ -935,7 +961,7 @@ class projectModel extends model
$product->createdDate = helper::now();
$product->status = 'normal';
$product->createdVersion = $this->config->version;
$product->vision = zget($project, 'vision', 'common');
$product->vision = zget($project, 'vision', 'rnd');
$this->dao->insert(TABLE_PRODUCT)->data($product)->exec();
$productID = $this->dao->lastInsertId();
+3 -2
View File
@@ -103,11 +103,12 @@ class search extends control
if($_POST)
{
$queryID = $this->search->saveQuery();
if(!$queryID) die(js::error(dao::getError()));
if(!$queryID) return print(js::error(dao::getError()));
$data = fixer::input('post')->get();
$shortcut = empty($data->onMenuBar) ? 0 : 1;
die(js::closeModal('parent.parent', '', "function(){parent.parent.loadQueries($queryID, $shortcut, '{$data->title}')}"));
return print(js::closeModal('parent.parent', '', "function(){parent.parent.loadQueries($queryID, $shortcut, '{$data->title}')}"));
}
$this->view->module = $module;
$this->view->onMenuBar = $onMenuBar;
+1
View File
@@ -29,6 +29,7 @@ $lang->search->me = 'Me';
$lang->search->noQuery = 'No query is saved yet!';
$lang->search->onMenuBar = 'Show in Menu';
$lang->search->custom = 'Custom';
$lang->search->setCommon = 'Set as public query criteria';
$lang->search->account = 'Account';
$lang->search->module = 'Module';
+1
View File
@@ -29,6 +29,7 @@ $lang->search->me = '自己';
$lang->search->noQuery = '还没有保存查询!';
$lang->search->onMenuBar = '显示在菜单栏';
$lang->search->custom = '自定义';
$lang->search->setCommon = '设为公共查询条件';
$lang->search->account = '用户名';
$lang->search->module = '模块';
+4
View File
@@ -403,7 +403,11 @@ class searchModel extends model
{
$queries = $this->dao->select('id, title')
->from(TABLE_USERQUERY)
->where()
->markLeft(1)
->where('account')->eq($this->app->user->account)
->orWhere('common')->eq(1)
->markRight(1)
->andWhere('module')->eq($module)
->orderBy('id_desc')
->fetchPairs();
+6
View File
@@ -14,6 +14,12 @@
<form target='hiddenwin' method='post' style='padding: 15px 70px 15px 15px'>
<div class='input-group'>
<input name='title' id='title' class="form-control" autocomplete="off" type="text">
<span class='input-group-addon'>
<div class="checkbox-primary">
<input type="checkbox" name="common" value="1" id="common" />
<label for="common"><?php echo $lang->search->setCommon;?></label>
</div>
</span>
<?php if($onMenuBar == 'yes'):?>
<span class='input-group-addon'>
<div class="checkbox-primary">
+5 -2
View File
@@ -832,8 +832,11 @@ class story extends control
foreach($branchList as $branchInfo) $branches[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
$branchTagOption[$linkedProduct->id] = array(BRANCH_MAIN => $this->lang->branch->main) + $branches;
$modules[$linkedProduct->id] = $this->tree->getOptionMenu($linkedProduct->id, 'story', 0, array_keys($branchList));
$plans[$linkedProduct->id] = $this->productplan->getBranchPlanPairs($linkedProduct->id, array_keys($branchList), true);
$moduleList = $this->tree->getOptionMenu($linkedProduct->id, 'story', 0, array_keys($branchList));
$modules[$linkedProduct->id] = $linkedProduct->type != 'normal' ? $moduleList : array(0 => $moduleList);
$plans[$linkedProduct->id] = $this->productplan->getBranchPlanPairs($linkedProduct->id, array_keys($branchList), true);
if(empty($plans[$linkedProduct->id])) $plans[$linkedProduct->id][0] = $plans[$linkedProduct->id];
if($linkedProduct->type != 'normal') $branchProduct = true;
+6 -5
View File
@@ -1522,9 +1522,9 @@ class storyModel extends model
->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty')
->where('id')->eq($storyID)->exec();
/* Update parent story status. */
/* Update parent story status and stage. */
if($oldStory->parent > 0) $this->updateParentStatus($storyID, $oldStory->parent);
$this->setStage($storyID);
$this->setStage($oldStory->parent);
if(!dao::isError()) $this->loadModel('score')->create('story', 'close', $storyID);
return common::createChanges($oldStory, $story);
}
@@ -2892,6 +2892,7 @@ class storyModel extends model
$stories = $sql->where('t1.deleted')->eq(0)
->andWhere('t1.type')->eq($storyType)
->andWhere('t1.vision')->eq($this->config->vision)
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi()
->beginIF($type != 'all')
->beginIF($type == 'assignedTo')->andWhere('assignedTo')->eq($account)->fi()
@@ -3905,7 +3906,7 @@ class storyModel extends model
}
break;
case 'taskCount':
$tasksLink = helper::createLink('story', 'tasks', "storyID=$story->id");
$tasksLink = helper::createLink('story', 'tasks', "storyID=$story->id", '', 'class="iframe"');
$storyTasks[$story->id] > 0 ? print(html::a($tasksLink, $storyTasks[$story->id], '', 'class="iframe"')) : print(0);
break;
case 'bugCount':
@@ -3982,9 +3983,9 @@ class storyModel extends model
common::printIcon('story', 'recall', $vars, $story, 'list', 'back', 'hiddenwin', '', '', '', $this->lang->story->recall);
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
if($story->type != 'requirement') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
if($story->type != 'requirement' and $this->config->vision != 'lite') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
if($this->app->rawModule != 'projectstory' OR $this->config->vision == 'lite') common::printIcon('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&storyID=$story->id", $story, 'list', 'split', '', '', '', '', $this->lang->story->subdivide);
if($this->app->rawModule == 'projectstory') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
if($this->app->rawModule == 'projectstory' and $this->config->vision != 'lite') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
}
else
{
+2 -2
View File
@@ -3,8 +3,8 @@ $config->user = new stdclass();
$config->user->create = new stdclass();
$config->user->edit = new stdclass();
$config->user->create->requiredFields = 'account,realname,password,password1,password2';
$config->user->edit->requiredFields = 'account,realname';
$config->user->create->requiredFields = 'account,realname,visions,password,password1,password2';
$config->user->edit->requiredFields = 'account,realname,visions';
$config->user->availableBatchCreateFields = 'dept,email,gender,commiter,join,skype,qq,dingding,weixin,mobile,slack,whatsapp,phone,address,zipcode';
$config->user->availableBatchEditFields = 'dept,email,commiter,skype,qq,dingding,weixin,mobile,slack,whatsapp,phone,address,zipcode';
+1
View File
@@ -977,6 +977,7 @@ class user extends control
/* Check deny type. */
$rights = $this->app->user->rights['rights'];
$acls = $this->app->user->rights['acls'];
$module = strtolower($module);
$method = strtolower($method);
+2 -1
View File
@@ -2,6 +2,7 @@ th.required:after {position: relative; right: 10px;}
td .passwordBox {border-left-width: 0px!important;}
.c-id {width: 40px;}
.c-dept {width: 150px;}
.c-dept {width: 120px;}
.c-realname {width: 130px;}
.c-visions {width: 130px;}
.c-role, .c-group, .c-commiter, .c-join, .c-contact {width: 120px;}
+1 -1
View File
@@ -1,2 +1,2 @@
.accountThWidth {width: 200px !important;}
.accountThWidth {width: 120px !important;}
.genderThWidth {width: 140px !important;}
+1 -1
View File
@@ -1,2 +1,2 @@
.accountThWidth {width: 180px !important;}
.accountThWidth {width: 120px !important;}
.genderThWidth {width: 100px !important;}
+1 -1
View File
@@ -1,2 +1,2 @@
.accountThWidth {width: 180px !important;}
.accountThWidth {width: 120px !important;}
.genderThWidth {width: 100px !important;}
+1
View File
@@ -0,0 +1 @@
.checkbox-primary {display:inline-block; padding-right:10px;}
+1
View File
@@ -42,6 +42,7 @@ $lang->user->address = '通讯地址';
$lang->user->zipcode = '邮编';
$lang->user->join = '入职日期';
$lang->user->visits = '访问次数';
$lang->user->visions = '版本类型';
$lang->user->ip = '最后IP';
$lang->user->last = '最后登录';
$lang->user->ranzhi = 'ZDOO帐号';
+35 -1
View File
@@ -302,9 +302,11 @@ class userModel extends model
->setDefault('join', '0000-00-00')
->setDefault('type', 'inside')
->setDefault('company', 0)
->setDefault('visions', '')
->setIF($this->post->password1 != false, 'password', substr($this->post->password1, 0, 32))
->setIF($this->post->password1 == false, 'password', '')
->setIF($this->post->email != false, 'email', trim($this->post->email))
->join('visions', ',')
->remove('new, group, password1, password2, verifyPassword, passwordStrength')
->get();
@@ -392,7 +394,8 @@ class userModel extends model
if($users->email[$i] and !validater::checkEmail($users->email[$i])) die(js::error(sprintf($this->lang->user->error->mail, $i + 1)));
$users->password[$i] = (isset($prev['password']) and $users->ditto[$i] == 'on' and !$this->post->password[$i]) ? $prev['password'] : $this->post->password[$i];
if(!validater::checkReg($users->password[$i], '|(.){6,}|')) die(js::error(sprintf($this->lang->user->error->password, $i + 1)));
$role = $users->role[$i] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : '') : $users->role[$i];
$role = $users->role[$i] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : '') : $users->role[$i];
$visions = in_array('ditto', $users->visions[$i]) ? (isset($prev['visions']) ? $prev['visions'] : array()) : $users->visions[$i];
/* Check weak and common weak password. */
if(isset($this->config->safe->mode) and $this->computePasswordStrength($users->password[$i]) < $this->config->safe->mode) die(js::error(sprintf($this->lang->user->error->weakPassword, $i + 1)));
@@ -424,6 +427,7 @@ class userModel extends model
$data[$i]->phone = $users->phone[$i];
$data[$i]->address = $users->address[$i];
$data[$i]->zipcode = $users->zipcode[$i];
$data[$i]->visions = join(',', $visions);
/* Check required fields. */
foreach(explode(',', $this->config->user->create->requiredFields) as $field)
@@ -454,6 +458,7 @@ class userModel extends model
$prev['dept'] = $data[$i]->dept;
$prev['role'] = $data[$i]->role;
$prev['group'] = $data[$i]->group;
$prev['visions'] = $users->visions[$i];
$prev['password'] = $users->password[$i];
}
}
@@ -509,8 +514,10 @@ class userModel extends model
$user = fixer::input('post')
->setDefault('join', '0000-00-00')
->setDefault('company', 0)
->setDefault('visions', '')
->setIF($this->post->password1 != false, 'password', substr($this->post->password1, 0, 32))
->setIF($this->post->email != false, 'email', trim($this->post->email))
->join('visions', ',')
->remove('new, password1, password2, groups,verifyPassword, passwordStrength')
->get();
@@ -552,6 +559,7 @@ class userModel extends model
->checkIF($this->post->mobile != '', 'mobile', 'mobile')
->where('id')->eq((int)$userID)
->exec();
if(dao::isError()) return false;
/* If account changed, update the privilege. */
if($this->post->account != $oldUser->account)
@@ -654,6 +662,7 @@ class userModel extends model
$users[$id]['phone'] = $data->phone[$id];
$users[$id]['address'] = $data->address[$id];
$users[$id]['zipcode'] = $data->zipcode[$id];
$users[$id]['visions'] = !empty($data->visions[$id]) ? join(',', $data->visions[$id]) : '';
$users[$id]['dept'] = $data->dept[$id] == 'ditto' ? (isset($prev['dept']) ? $prev['dept'] : 0) : $data->dept[$id];
$users[$id]['role'] = $data->role[$id] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : 0) : $data->role[$id];
@@ -1017,6 +1026,13 @@ class userModel extends model
$projectAdminGroupID = $this->dao->select('id')->from(TABLE_GROUP)->where('role')->eq('projectAdmin')->fetch('id');
$canManageProjects = $this->dao->select('project')->from(TABLE_USERGROUP)->where('`group`')->eq($projectAdminGroupID)->andWhere('account')->eq($account)->fetch('project');
}
/* Set basic priv when no any priv. */
if(empty($rights))
{
$rights['index']['index'] = 1;
$rights['my']['index'] = 1;
}
return array('rights' => $rights, 'acls' => $acls, 'projects' => $canManageProjects);
}
@@ -1114,6 +1130,7 @@ class userModel extends model
->beginIF($type == 'project' and !$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->projects)->fi()
->andWhere('t1.account')->eq($account)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.vision')->eq($this->config->vision)
->orderBy("t2.$orderBy")
->page($pager)
->fetchAll('root');
@@ -2656,4 +2673,21 @@ class userModel extends model
}
return $userDetails;
}
/**
* Get vision list.
*
* @access public
* @return array
*/
public function getVisionList()
{
$visionList = $this->lang->visionList;
foreach($visionList as $visionKey => $visionName)
{
if(strpos($this->config->visions, ",{$visionKey},") === false) unset($visionList[$visionKey]);
}
return $visionList;
}
}
+5 -2
View File
@@ -49,6 +49,7 @@
<th class='c-dept<?php echo zget($visibleFields, 'dept', ' hidden') . zget($requiredFields, 'dept', '', ' required');?>'> <?php echo $lang->user->dept;?></th>
<th class='accountThWidth required'><?php echo $lang->user->account;?></th>
<th class='c-realname required'><?php echo $lang->user->realname;?></th>
<th class='c-visions required'><?php echo $lang->user->visions;?></th>
<th class='c-role<?php echo zget($requiredFields, 'role', '', ' required')?>'><?php echo $lang->user->role;?></th>
<th class='c-group'><?php echo $lang->user->group;?></th>
<th class='<?php echo zget($visibleFields, 'email', "$minWidth hidden", $minWidth) . zget($requiredFields, 'email', '', ' required')?>'><?php echo $lang->user->email;?></th>
@@ -71,13 +72,15 @@
<tbody>
<?php $depts = $depts + array('ditto' => $lang->user->ditto)?>
<?php $lang->user->roleList = $lang->user->roleList + array('ditto' => $lang->user->ditto)?>
<?php $groupList = $groupList + array('ditto' => $lang->user->ditto)?>
<?php $groupList = $groupList + array('ditto' => $lang->user->ditto);?>
<?php $visionList = $this->user->getVisionList() + array('ditto' => $lang->user->ditto);?>
<?php for($i = 0; $i < $config->user->batchCreate; $i++):?>
<tr class='text-center'>
<td><?php echo $i+1;?></td>
<td><?php echo $i + 1;?></td>
<td class='text-left<?php echo zget($visibleFields, 'dept', ' hidden')?>' style='overflow:visible'><?php echo html::select("dept[$i]", $depts, $i > 0 ? 'ditto' : $deptID, "class='form-control chosen'");?></td>
<td><?php echo html::input("account[$i]", '', "class='form-control account_$i' onchange='changeEmail($i)'");?></td>
<td><?php echo html::input("realname[$i]", '', "class='form-control'");?></td>
<td class='text-left'><?php echo html::select("visions[$i][]", $visionList, $i > 0 ? 'ditto' : '', "class='form-control chosen' multiple");?></td>
<td><?php echo html::select("role[$i]", $lang->user->roleList, $i > 0 ? 'ditto' : '', "class='form-control' onchange='changeGroup(this.value, $i)'");?></td>
<td class='text-left' style='overflow:visible'><?php echo html::select("group[$i]", $groupList, $i > 0 ? 'ditto' : '', "class='form-control chosen'");?></td>
<td <?php echo zget($visibleFields, 'email', "class='hidden'")?>><?php echo html::input("email[$i]", '', "class='form-control email_$i' onchange='setDefaultEmail($i)'");?></td>
+6 -3
View File
@@ -44,10 +44,11 @@
<table class="table table-form">
<thead>
<tr class='text-center'>
<th class='w-30px'><?php echo $lang->idAB;?></th>
<th class='w-30px'><?php echo $lang->idAB;?></th>
<th class='w-150px<?php echo zget($visibleFields, 'dept', ' hidden')?>'> <?php echo $lang->user->dept;?></th>
<th class='<?php echo $minWidth?> required'><?php echo $lang->user->account;?></th>
<th class='<?php echo $minWidth?> required'><?php echo $lang->user->realname;?></th>
<th class='w-130px'><?php echo $lang->user->visions;?></th>
<th class='w-120px'><?php echo $lang->user->role;?></th>
<th class='w-120px'><?php echo $lang->user->type;?></th>
<th class='<?php echo $minWidth . zget($visibleFields, 'commiter', ' hidden')?>'><?php echo $lang->user->commiter;?></th>
@@ -71,8 +72,8 @@
<?php $first = true;?>
<?php foreach($users as $user):?>
<?php
$dept = ($first and empty($user->dept)) ? 0 : (empty($user->dept) ? 'ditto' : $user->dept);
$role = ($first and empty($user->role)) ? 0 : (empty($user->role) ? 'ditto' : $user->role);
$dept = ($first and empty($user->dept)) ? 0 : (empty($user->dept) ? 'ditto' : $user->dept);
$role = ($first and empty($user->role)) ? 0 : (empty($user->role) ? 'ditto' : $user->role);
$type = empty($user->type) ? 'inside' : $user->type;
$first = false;
?>
@@ -81,6 +82,8 @@
<td class='text-left<?php echo zget($visibleFields, 'dept', ' hidden')?>' style='overflow:visible'><?php echo html::select("dept[$user->id]", $depts, $dept, "class='form-control chosen'");?></td>
<td><?php echo html::input("account[$user->id]", $user->account, "class='form-control'");?></td>
<td><?php echo html::input("realname[$user->id]", $user->realname, "class='form-control'");?></td>
<?php $visionList = $this->user->getVisionList();?>
<td class='text-left'><?php echo html::select("visions[$user->id][]", $visionList, $user->visions, "class='form-control chosen' multiple");?></td>
<td><?php echo html::select("role[$user->id]", $lang->user->roleList, $role, "class='form-control'");?></td>
<td><?php echo html::select("type[$user->id]", $lang->user->typeList, $type, "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'commiter', 'hidden')?>'><?php echo html::input("commiter[$user->id]", $user->commiter, "class='form-control'");?></td>
+5
View File
@@ -60,6 +60,11 @@
<th><?php echo $lang->user->password2;?></th>
<td><?php echo html::password('password2', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->user->visions;?></th>
<?php $visionList = $this->user->getVisionList();?>
<td><?php echo html::checkbox('visions', $visionList, key($visionList), "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->user->realname;?></th>
<td><?php echo html::input('realname', '', "class='form-control'");?></td>
+3
View File
@@ -81,6 +81,9 @@
<tr>
<th><?php echo $lang->user->commiter;?></th>
<td><?php echo html::input('commiter', $user->commiter, "class='form-control'");?></td>
<th><?php echo $lang->user->visions;?></th>
<?php $visionList = $this->user->getVisionList();?>
<td><?php echo html::select('visions[]', $visionList, $user->visions, "class='form-control chosen' multiple");?></td>
</tr>
</table>
<table align='center' class='table table-form'>
+7 -3
View File
@@ -43,9 +43,13 @@
<tr class='colhead'>
<th class='w-id'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
<th class='w-pri'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
<?php if($this->config->vision == 'lite'):?>
<th class='w-200px'><?php common::printOrderLink('product', $orderBy, $vars, $lang->story->project);?></th>
<?php else:?>
<th class='w-200px'><?php common::printOrderLink('product', $orderBy, $vars, $lang->story->product);?></th>
<?php endif;?>
<th> <?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
<?php if($storyType != 'requirement'):?>
<?php if($storyType != 'requirement' and $this->config->vision != 'lite'):?>
<th class='w-150px'><?php common::printOrderLink('plan', $orderBy, $vars, $lang->story->plan);?></th>
<?php endif;?>
<th class='w-90px'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
@@ -56,13 +60,13 @@
</thead>
<tbody>
<?php foreach($stories as $key => $story):?>
<?php $storyLink = $this->createLink('story', 'view', "id=$story->id");?>
<?php $storyLink = $this->createLink('story', 'view', "id=$story->id");?>
<tr class='text-left'>
<td><?php echo html::a($storyLink, sprintf('%03d', $story->id));?></td>
<td><span class='<?php echo 'pri' . zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri);?></span></td>
<td><?php echo $story->productTitle;?></td>
<td class='text-left nobr'><?php echo html::a($storyLink, $story->title);?></td>
<?php if($storyType != 'requirement'):?>
<?php if($storyType != 'requirement' and $this->config->vision != 'lite'):?>
<td title='<?php echo $story->planTitle;?>'><?php echo $story->planTitle;?></td>
<?php endif;?>
<td><?php echo zget($users, $story->openedBy);?></td>