* Finish task #36496.
This commit is contained in:
@@ -672,15 +672,10 @@ class actionModel extends model
|
||||
|
||||
/* If is project, select its related. */
|
||||
$executions = array();
|
||||
$products = array();
|
||||
if(is_numeric($projectID))
|
||||
{
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(isset($project->type) and $project->type == 'project')
|
||||
{
|
||||
$executions = $this->loadModel('execution')->getPairs($projectID);
|
||||
$products = $this->loadModel('product')->getProductPairsByProject($projectID);
|
||||
}
|
||||
if(isset($project->type) and $project->type == 'project') $executions = $this->loadModel('execution')->getPairs($projectID);
|
||||
}
|
||||
|
||||
$this->loadModel('doc');
|
||||
@@ -697,9 +692,12 @@ class actionModel extends model
|
||||
->beginIF($date)->andWhere('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")->fi()
|
||||
->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi()
|
||||
->beginIF(is_numeric($productID))->andWhere('product')->like("%,$productID,%")->fi()
|
||||
->beginIF(is_numeric($projectID))->andWhere('execution')->eq($projectID)->fi()
|
||||
->beginIF(!empty($executions))->markLeft()->orWhere('execution')->in($executions)->fi()->markRight()
|
||||
->beginIF(!empty($products))->markLeft()->orWhere('product')->in($products)->fi()->markRight()
|
||||
->andWhere()
|
||||
->markLeft(1)
|
||||
->where(1)
|
||||
->beginIF(is_numeric($projectID))->orWhere('execution')->eq($projectID)->fi()
|
||||
->beginIF(!empty($executions))->orWhere('execution')->in(array_keys($executions))->fi()
|
||||
->markRight(1)
|
||||
->beginIF($productID == 'notzero')->andWhere('product')->gt(0)->andWhere('product')->notlike('%,0,%')->fi()
|
||||
->beginIF($projectID == 'notzero')->andWhere('execution')->gt(0)->fi()
|
||||
->beginIF($projectID == 'all' or $productID == 'all')->andWhere("IF((objectType!= 'doc' && objectType!= 'doclib'), ($condition), '1=1')")->fi()
|
||||
|
||||
@@ -896,7 +896,7 @@ $lang->menu->scrum->qa = '测试|qa|index';
|
||||
$lang->menu->scrum->ci = '代码|repo|browse';
|
||||
$lang->menu->scrum->projectbuild = array('link' => '版本|projectbuild|browse|project={PROJECT}');
|
||||
$lang->menu->scrum->projectrelease = array('link' => '发布|projectrelease|browse|project={PROJECT}');
|
||||
$lang->menu->scrum->dynamic = array('link' => '动态|project|dynamic');
|
||||
$lang->menu->scrum->dynamic = array('link' => '动态|project|dynamic|project={PROJECT}');
|
||||
$lang->menu->scrum->other = array('link' => '其他|project|other', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'issue,risk,stakeholder');
|
||||
$lang->menu->scrum->projectsetting = array('link' => '设置|project|view|project={PROJECT}', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist');
|
||||
|
||||
|
||||
@@ -580,6 +580,74 @@ class project extends control
|
||||
$this->display('group', 'create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Project dynamic.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $type
|
||||
* @param string $param
|
||||
* @param int $recTotal
|
||||
* @param string $date
|
||||
* @param string $direction next|pre
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function dynamic($projectID = 0, $type = 'today', $param = '', $recTotal = 0, $date = '', $direction = 'next')
|
||||
{
|
||||
@ini_set('memory_limit', '2048M');
|
||||
/* Save session. */
|
||||
$uri = $this->app->getURI(true);
|
||||
$this->session->set('productList', $uri);
|
||||
$this->session->set('productPlanList', $uri);
|
||||
$this->session->set('releaseList', $uri);
|
||||
$this->session->set('storyList', $uri);
|
||||
$this->session->set('executionList', $uri);
|
||||
$this->session->set('taskList', $uri);
|
||||
$this->session->set('buildList', $uri);
|
||||
$this->session->set('bugList', $uri);
|
||||
$this->session->set('caseList', $uri);
|
||||
$this->session->set('testtaskList', $uri);
|
||||
|
||||
/* Append id for secend sort. */
|
||||
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
|
||||
/* Set the pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage = 50, $pageID = 1);
|
||||
|
||||
/* Set the user and type. */
|
||||
$account = 'all';
|
||||
if($type == 'account')
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($param, 'account');
|
||||
if($user) $account = $user->account;
|
||||
}
|
||||
$period = $type == 'account' ? 'all' : $type;
|
||||
$date = empty($date) ? '' : date('Y-m-d', $date);
|
||||
$actions = $this->loadModel('action')->getDynamic($account, $period, $sort, $pager, 'all', $projectID, $date, $direction);
|
||||
|
||||
/* The header and position. */
|
||||
$project = $this->project->getByID($projectID);
|
||||
$this->view->title = $project->name . $this->lang->colon . $this->lang->project->dynamic;
|
||||
$this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name);
|
||||
$this->view->position[] = $this->lang->project->dynamic;
|
||||
|
||||
$this->view->userIdPairs = $this->project->getTeamMemberPairs($project->parent);
|
||||
$this->view->accountPairs = $this->loadModel('user')->getPairs('noletter|nodeleted');
|
||||
|
||||
/* Assign. */
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->type = $type;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->account = $account;
|
||||
$this->view->param = $param;
|
||||
$this->view->dateGroups = $this->action->buildDateGroup($actions, $direction, $type);
|
||||
$this->view->direction = $direction;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Project manage view.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#mainMenu .btn-group ul.dropdown-menu{max-height: 300px; overflow: auto;}
|
||||
#dynamics {padding: 10px 0;}
|
||||
.dynamic {position: relative; padding-left: 170px;}
|
||||
.dynamic-date {position: absolute; left: 0; top: 0; width: 150px; border: 2px solid #eee; border-radius: 4px; padding: 14px 20px; height: 58px;}
|
||||
.dynamic-date:before {content: ' '; display: block; position: absolute; right: -22px; top: 26px; height: 2px; width: 20px; background-color: #eee;}
|
||||
.dynamic-date > .date-label,
|
||||
.dynamic-date > .date-text {font-size: 18px; display: block;}
|
||||
.dynamic-date > .date-label + .date-text {font-size: 14px; line-height: 14px;}
|
||||
.dynamic-date > .date-label {margin-top: -8px;}
|
||||
.dynamic-date > .btn {position: absolute; right: 10px; top: 15px;}
|
||||
.dynamic .timeline {border: 2px solid #eee; border-radius: 4px; margin-bottom: 20px; padding: 10px 20px 10px 100px; transition: max-height .2s; overflow: hidden;}
|
||||
.dynamic .timeline-tag {left: -75px; font-size: 14px; color: #838A9D;}
|
||||
.dynamic .timeline-text {color: #3C4353;}
|
||||
.dynamic .text-muted {color: #838A9D;}
|
||||
.dynamic .label-id {top: -1px;}
|
||||
.dynamic.active .timeline,
|
||||
.dynamic.active .dynamic-date {border-color: #00a9fc;}
|
||||
.dynamic.active .dynamic-date:before {background-color: #00a9fc;}
|
||||
.dynamic.collapsed .timeline {max-height: 58px;}
|
||||
.dynamic.collapsed .timeline > li + li {display: none;}
|
||||
.dynamic.collapsed .dynamic-btn > .icon:before {content: '\f0d8'; }
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* The action->dynamic view file of dashboard module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package dashboard
|
||||
* @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php foreach($lang->action->periods as $period => $label):?>
|
||||
<?php
|
||||
$label = "<span class='text'>$label</span>";
|
||||
$active = '';
|
||||
if($period == $type)
|
||||
{
|
||||
$active = 'btn-active-text';
|
||||
$label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";
|
||||
}
|
||||
echo html::a(inlink('dynamic', "projectID=$projectID&type=$period"), $label, '', "class='btn btn-link $active' id='{$period}'")
|
||||
?>
|
||||
<?php endforeach;?>
|
||||
<div class="btn-group">
|
||||
<?php
|
||||
$withSearch = count($accountPairs) > 8;
|
||||
$active = $param ? 'btn-active-text' : '';
|
||||
$current = $param ? zget($accountPairs, $account, $account) : $lang->execution->viewByUser;
|
||||
$current = "<span class='text'>" . $current . '</span>' . ' <span class="caret"></span>';
|
||||
?>
|
||||
<?php echo html::a('###', $current, '', "class='btn btn-link $active' data-toggle='dropdown'");?>
|
||||
<div class="dropdown-menu search-list<?php if($withSearch) echo ' search-box-sink';?>" data-ride="searchList">
|
||||
<?php if($withSearch):?>
|
||||
<div class="input-control search-box has-icon-left has-icon-right search-example">
|
||||
<input id="userSearchBox" type="search" autocomplete="off" class="form-control search-input">
|
||||
<label for="userSearchBox" class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label>
|
||||
<a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class='list-group'>
|
||||
<?php
|
||||
$usersPinYin = common::convert2Pinyin($userIdPairs);
|
||||
foreach($userIdPairs as $userID => $name)
|
||||
{
|
||||
if(!$userID) continue;
|
||||
$searchKey = $withSearch ? ('data-key="' . zget($usersPinYin, $name, '') . '"') : '';
|
||||
echo html::a($this->createLink('project', 'dynamic', "projectID=$projectID&type=account¶m=$userID"), $name, '', $searchKey);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mainContent" class="main-content">
|
||||
<?php if(empty($dateGroups)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->action->noDynamic;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div id="dynamics">
|
||||
<?php $firstAction = '';?>
|
||||
<?php foreach($dateGroups as $date => $actions):?>
|
||||
<?php $isToday = date(DT_DATE4) == $date;?>
|
||||
<div class="dynamic <?php if($isToday) echo 'active';?>">
|
||||
<div class="dynamic-date <?php if($type == 'all') echo 'w-200px';?>">
|
||||
<?php if($isToday):?>
|
||||
<span class="date-label"><?php echo $lang->action->dynamic->today;?></span>
|
||||
<?php endif;?>
|
||||
<span class="date-text"><?php echo $date;?></span>
|
||||
<button type="button" class="btn btn-info btn-icon btn-sm dynamic-btn"><i class="icon icon-caret-down"></i></button>
|
||||
</div>
|
||||
<ul class="timeline timeline-tag-left <?php if($type == 'all') echo 'margin-l-50px';?>">
|
||||
<?php if($direction == 'next') $actions = array_reverse($actions);?>
|
||||
<?php foreach($actions as $i => $action):?>
|
||||
<?php if(empty($firstAction)) $firstAction = $action;?>
|
||||
<li <?php if($action->major) echo "class='active'";?>>
|
||||
<div>
|
||||
<span class="timeline-tag"><?php echo $action->time?></span>
|
||||
<span class="timeline-text">
|
||||
<?php echo zget($accountPairs, $action->actor);?>
|
||||
<span class='label-action'><?php echo ' ' . $action->actionLabel;?></span>
|
||||
<span class="text"><?php echo $action->objectLabel;?></span>
|
||||
<span class="label label-id"><?php echo $action->objectID;?></span>
|
||||
<?php echo html::a($action->objectLink, $action->objectName);?>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php if(!empty($firstAction)):?>
|
||||
<?php
|
||||
$firstDate = date('Y-m-d', strtotime($firstAction->originalDate) + 24 * 3600);
|
||||
$lastDate = substr($action->originalDate, 0, 10);
|
||||
$hasPre = $this->action->hasPreOrNext($firstDate, 'pre');
|
||||
$hasNext = $this->action->hasPreOrNext($lastDate, 'next');
|
||||
$preLink = $hasPre ? inlink('dynamic', "projectID=$projectID&type=$type¶m=$param&recTotal={$pager->recTotal}&date=" . strtotime($firstDate) . '&direction=pre') : 'javascript:;';
|
||||
$nextLink = $hasNext ? inlink('dynamic', "projectID=$projectID&type=$type¶m=$param&recTotal={$pager->recTotal}&date=" . strtotime($lastDate) . '&direction=next') : 'javascript:;';
|
||||
?>
|
||||
<?php if($hasPre or $hasNext):?>
|
||||
<div id="mainActions" class='main-actions'>
|
||||
<nav class="container">
|
||||
<a id="prevPage" class="btn btn-info<?php if(!$hasNext) echo ' disabled';?>" href="<?php echo $nextLink;?>"><i class="icon icon-chevron-left"></i></a>
|
||||
<a id="nextPage" class="btn btn-info<?php if(!$hasPre) echo ' disabled';?>" href="<?php echo $preLink;?>"><i class="icon icon-chevron-right"></i></a>
|
||||
</nav>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$('#dynamics').on('click', '.dynamic-btn', function()
|
||||
{
|
||||
$(this).closest('.dynamic').toggleClass('collapsed');
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
Reference in New Issue
Block a user