Merge branch '20.x' of https://github.com/easysoft/zentaopms into 20.x
This commit is contained in:
@@ -705,7 +705,7 @@ class block extends control
|
||||
foreach($programs as $programID => $program)
|
||||
{
|
||||
$members = $this->project->getTeamMemberPairs($programID);
|
||||
$consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->ne('cancel')->fetch('consumed');
|
||||
$consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('parent')->lt(1)->fetch('consumed');
|
||||
$leftTasks = $this->dao->select('count(*) as leftTasks')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->in('wait,doing,pause')->fetch('leftTasks');
|
||||
$leftStories = $this->dao->select('count(*) as leftStories')->from(TABLE_STORY)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->eq('active')->fetch('leftStories');
|
||||
$leftBugs = $this->dao->select('count(*) as leftBugs')->from(TABLE_BUG)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->eq('active')->fetch('leftBugs');
|
||||
@@ -762,6 +762,64 @@ class block extends control
|
||||
$this->$func();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print project statistic block.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printProgramStatisticBlock()
|
||||
{
|
||||
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
|
||||
|
||||
$this->loadModel('project');
|
||||
$this->app->loadLang('task');
|
||||
$this->app->loadLang('story');
|
||||
|
||||
$status = isset($this->params->type) ? $this->params->type : 'all';
|
||||
$num = isset($this->params->num) ? (int)$this->params->num : 15;
|
||||
|
||||
/* Get projects. */
|
||||
$programs = $this->loadModel('program')->getUserPrograms($status, 'id_desc', $num);
|
||||
if(empty($programs))
|
||||
{
|
||||
$this->view->programs = $programs;
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($programs as $programID => $program)
|
||||
{
|
||||
$program->allStories = $program->doneStories = $program->leftStories = 0;
|
||||
$program->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)
|
||||
->where('program')->eq($programID)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('parent')->lt(1)
|
||||
->fetch('consumed');
|
||||
|
||||
$members = $this->project->getTeamMemberPairs($programID);
|
||||
$program->countMembers = count($members) ? count($members) - 1 : 0;
|
||||
|
||||
$stories = $this->dao->select('id, status')->from(TABLE_STORY)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('type')->eq('story')
|
||||
->andWhere('status')->ne('draft')
|
||||
->andWhere('program')->eq($programID)
|
||||
->fetchPairs();
|
||||
foreach($stories as $id => $status)
|
||||
{
|
||||
$program->allStories ++;
|
||||
if($status == 'closed') $program->doneStories ++;
|
||||
if($status != 'closed') $program->leftStories ++;
|
||||
}
|
||||
|
||||
$program->progress = $program->allStories == 0 ? 0 : ceil($program->doneStories / $program->allStories) * 100;
|
||||
|
||||
//$program->projects = $this->dao->select('*')
|
||||
}
|
||||
|
||||
$this->view->programs = $programs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print product statistic block.
|
||||
*
|
||||
@@ -1089,7 +1147,7 @@ class block extends control
|
||||
|
||||
$this->view->people = $this->dao->select('sum(people) as people')->from(TABLE_DURATIONESTIMATION)->where('program')->eq($this->session->program)->fetch('people');
|
||||
$this->view->members = count($members) ? count($members) - 1 : 0;
|
||||
$this->view->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->ne('cancel')->fetch('consumed');
|
||||
$this->view->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('parent')->lt(1)->fetch('consumed');
|
||||
$this->view->budget = $budget;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,8 +245,10 @@ $lang->block->default['full']['my']['3']['grid'] = 4;
|
||||
$lang->block->default['full']['my']['3']['source'] = 'todo';
|
||||
$lang->block->default['full']['my']['3']['params']['num'] = '20';
|
||||
|
||||
$lang->block->default['full']['my']['4'] = $lang->block->default['project']['1'];
|
||||
$lang->block->default['full']['my']['4']['source'] = 'project';
|
||||
$lang->block->default['full']['my']['4']['title'] = '项目统计';
|
||||
$lang->block->default['full']['my']['4']['block'] = 'statistic';
|
||||
$lang->block->default['full']['my']['4']['source'] = 'program';
|
||||
$lang->block->default['full']['my']['4']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['5']['title'] = '个人贡献';
|
||||
$lang->block->default['full']['my']['5']['block'] = 'contribute';
|
||||
@@ -268,12 +270,12 @@ $lang->block->default['full']['my']['8']['title'] = '项目人力投入';
|
||||
$lang->block->default['full']['my']['8']['block'] = 'programteam';
|
||||
$lang->block->default['full']['my']['8']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['8']['title'] = '项目列表';
|
||||
$lang->block->default['full']['my']['8']['block'] = 'program';
|
||||
$lang->block->default['full']['my']['8']['grid'] = 8;
|
||||
$lang->block->default['full']['my']['9']['title'] = '项目列表';
|
||||
$lang->block->default['full']['my']['9']['block'] = 'program';
|
||||
$lang->block->default['full']['my']['9']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['8']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['full']['my']['8']['params']['num'] = '15';
|
||||
$lang->block->default['full']['my']['9']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['full']['my']['9']['params']['num'] = '15';
|
||||
|
||||
$lang->block->num = '数量';
|
||||
$lang->block->type = '类型';
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<style>
|
||||
.types-line {display: table; padding: 0; margin: 0 auto;}
|
||||
.types-line > li {display: table-cell;}
|
||||
.types-line > li > div {position: relative; padding: 18px 5px 5px; text-align: center;}
|
||||
.types-line > li > div:before {content: ''; display: block; background: #eee; width: 100%; height: 2px; position: absolute; left: 50%; top: 4px;}
|
||||
.types-line > li:last-child > div:before {display: none;}
|
||||
.types-line > li > div:after {content: ''; display: block; background: #FFFFFF; box-shadow: 0 2px 4px 0 rgba(170,170,170,0.50), 0 0 5px 0 rgba(0,0,0,0.1); width: 10px; height: 10px; position: absolute; border-radius: 50%; top: 0; left: 50%; margin-left: -2px;}
|
||||
.types-line > li > div > small {display: block; color: #A6AAB8;}
|
||||
.types-line > li > div > span {display: block; color: #CBD0DB; font-size: 16px;}
|
||||
.product-info {position: relative; height: 65px;}
|
||||
.product-info + .product-info {margin-top: 10px;}
|
||||
.product-info .progress {position: absolute; left: 10px; top: 35px; right: 100px;}
|
||||
.product-info .progress-info {position: absolute; left: 8px; top: 10px; width: 180px; font-size: 12px;}
|
||||
.product-info .type-info {color: #A6AAB8; text-align: center; position: absolute; right: 0; top: 6px; width: 100px;}
|
||||
html[lang="en"] .product-info .type-info {color: #A6AAB8; text-align: center; position: absolute; right: 0; top: 6px; width: 110px;}
|
||||
.product-info .type-value,
|
||||
.product-info .type-label {font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
.product-info .type-value {font-size: 14px;}
|
||||
.product-info .type-value > strong {font-size: 20px; color: #3C4353;}
|
||||
.product-info .actions {position: absolute; left: 10px; top: 14px;}
|
||||
.block-statistic .panel-body {padding-top: 0}
|
||||
.block-statistic .tile {margin-bottom: 30px;}
|
||||
.block-statistic .tile-title {font-size: 18px; color: #A6AAB8;}
|
||||
.block-statistic .tile-amount {font-size: 48px; margin-bottom: 10px;}
|
||||
.block-statistic .col-nav {border-right: 1px solid #EBF2FB; width: 260px; padding: 0;}
|
||||
.block-statistic .nav-secondary > li {position: relative}
|
||||
.block-statistic .nav-secondary > li > a {font-size: 14px; color: #838A9D; position: relative; box-shadow: none; padding-left: 20px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; transition: all .2s;}
|
||||
.block-statistic .nav-secondary > li > a:first-child {padding-right: 36px;}
|
||||
.block-statistic .nav-secondary > li.active > a:first-child {color: #3C4353; background: transparent; box-shadow: none;}
|
||||
.block-statistic .nav-secondary > li.active > a:first-child:hover,
|
||||
.block-statistic .nav-secondary > li.active > a:first-child:focus,
|
||||
.block-statistic .nav-secondary > li > a:first-child:hover {box-shadow: none; border-radius: 4px 0 0 4px;}
|
||||
.block-statistic .nav-secondary > li.active > a:first-child:before {content: ' '; display: block; left: -1px; top: 10px; bottom: 10px; width: 4px; background: #006af1; position: absolute;}
|
||||
.block-statistic .nav-secondary > li > a.btn-view {position: absolute; top: 0; right: 0; bottom: 0; padding: 8px; width: 36px; text-align: center; opacity: 0;}
|
||||
.block-statistic .nav-secondary > li:hover > a.btn-view {opacity: 1}
|
||||
.block-statistic .nav-secondary > li.active > a.btn-view {box-shadow: none}
|
||||
.block-statistic .nav-secondary > li.switch-icon {display: none;}
|
||||
.block-statistic.block-sm .panel-body {padding-bottom: 10px; position: relative; padding-top: 45px; border-radius: 3px;}
|
||||
.block-statistic.block-sm .panel-body > .table-row,
|
||||
.block-statistic.block-sm .panel-body > .table-row > .col {display: block; width: auto;}
|
||||
.block-statistic.block-sm .panel-body > .table-row > .tab-content {padding: 0; margin: 0 -5px;}
|
||||
.block-statistic.block-sm .tab-pane > .table-row > .col-5 {width: 125px;}
|
||||
.block-statistic.block-sm .tab-pane > .table-row > .col-5 > .table-row {padding: 5px 0;}
|
||||
.block-statistic.block-sm .col-nav {border-left: none; position: absolute; top: 0; left: 15px; right: 15px; background: #f5f5f5;}
|
||||
.block-statistic.block-sm .nav-secondary {display: table; width: 100%; padding: 0; table-layout: fixed;}
|
||||
.block-statistic.block-sm .nav-secondary > li {display: none}
|
||||
.block-statistic.block-sm .nav-secondary > li.switch-icon,
|
||||
.block-statistic.block-sm .nav-secondary > li.active {display: table-cell; width: 100%; text-align: center;}
|
||||
.block-statistic.block-sm .nav-secondary > li.active > a:hover {cursor: default; background: none;}
|
||||
.block-statistic.block-sm .nav-secondary > li.switch-icon > a:hover {background: rgba(0,0,0,0.07);}
|
||||
.block-statistic.block-sm .nav-secondary > li > a {padding: 5px 10px; border-radius: 4px;}
|
||||
.block-statistic.block-sm .nav-secondary > li > a:before {display: none;}
|
||||
.block-statistic.block-sm .nav-secondary > li.switch-icon {width: 40px;}
|
||||
.block-statistic.block-sm .nav-secondary > li.active > a:first-child:before {display: none}
|
||||
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view {width: auto; left: 0; right: 0;}
|
||||
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view > i {display: none;}
|
||||
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view:hover {cursor: pointer; background: rgba(0,0,0,.1)}
|
||||
|
||||
.status-count{margin:auto}
|
||||
.status-count tr:first-child td:last-child{color:#000;font-weight:bold}
|
||||
</style>
|
||||
<script>
|
||||
<?php $blockNavId = 'nav-' . uniqid(); ?>
|
||||
$(function()
|
||||
{
|
||||
var $nav = $('#<?php echo $blockNavId;?>');
|
||||
$nav.on('click', '.switch-icon', function(e)
|
||||
{
|
||||
var isPrev = $(this).is('.prev');
|
||||
var $activeItem = $nav.children('.active');
|
||||
var $next = $activeItem[isPrev ? 'prev' : 'next']('li:not(.switch-icon)');
|
||||
if ($next.length) $next.find('a').trigger('click');
|
||||
else $nav.children('li:not(.switch-icon)')[isPrev ? 'last' : 'first']().find('a').trigger('click');
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
var $programLi = $('#activeProject');
|
||||
if($programLi.length)
|
||||
{
|
||||
var programLi = $programLi[0];
|
||||
$(".col ul.nav").animate({scrollTop: programLi.offsetTop}, "slow");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div class="panel-body">
|
||||
<div class="table-row">
|
||||
<?php if(empty($programs)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->block->noData;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="col col-nav">
|
||||
<ul class="nav nav-stacked nav-secondary scrollbar-hover" id='<?php echo $blockNavId;?>'>
|
||||
<li class='switch-icon prev'><a><i class='icon icon-arrow-left'></i></a></li>
|
||||
<?php $selected = empty($_SESSION['program']) ? key($programs) : $this->session->program;?>
|
||||
<?php foreach($programs as $program):?>
|
||||
<li <?php if($program->id == $selected) echo "class='active' id='activeProject'";?> programID='<?php echo $program->id;?>'>
|
||||
<a href="###" data-target="#tab3Content<?php echo $program->id;?>" data-toggle="tab"><?php echo $program->name;?></a>
|
||||
<?php echo html::a(helper::createLink('program', 'index', "programID=$program->id"), "<i class='icon-arrow-right text-primary'></i>", '', "class='btn-view' title={$lang->program->index}");?>
|
||||
</li>
|
||||
<?php endforeach;?>
|
||||
<li class='switch-icon next'><a><i class='icon icon-arrow-right'></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col tab-content">
|
||||
<?php foreach($programs as $program):?>
|
||||
<div class="tab-pane fade<?php if($program->id == $selected) echo ' active in';?>" id="tab3Content<?php echo $program->id;?>">
|
||||
<div class="table-row">
|
||||
<div class="col-5 text-middle text-center">
|
||||
<div class="progress-pie inline-block space" data-value="<?php echo $program->progress;?>" data-doughnut-size="84">
|
||||
<canvas width="120" height="120"></canvas>
|
||||
<div class="progress-info">
|
||||
<small><?php echo $lang->story->common . $lang->program->doneStories;?></small>
|
||||
<strong><?php echo $program->doneStories;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row text-center small text-muted with-padding">
|
||||
<div class="col-4 text-bottom">
|
||||
<div><?php echo $lang->program->allStories;?></div>
|
||||
<div><?php echo $program->allStories;?></div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<span class="label label-dot label-primary"></span>
|
||||
<div><?php echo $lang->program->doneStories;?></div>
|
||||
<div><?php echo $program->doneStories;?></div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<span class="label label-dot label-pale"></span>
|
||||
<div><?php echo $lang->program->leftStories;?></div>
|
||||
<div><?php echo $program->leftStories;?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<div class="program-info">
|
||||
<div class='title'><?php echo $lang->program->allInput;?></div>
|
||||
<div class='info'>
|
||||
<span><i class='icon icon-group'></i><?php echo $program->countMembers;?></span>
|
||||
<span><i class='icon icon-clock'></i><?php echo $program->consumed;?></span>
|
||||
<span><i class='icon icon-yen'></i><?php echo $program->budget;?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-info">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
$lang->design->common = 'Design';
|
||||
$lang->design->browse = 'List';
|
||||
$lang->design->commit = 'Link Commit';
|
||||
$lang->design->submission = 'Commit';
|
||||
$lang->design->version = 'Revision';
|
||||
$lang->design->assignedTo = 'AssignedTo';
|
||||
$lang->design->actions = 'Actions';
|
||||
$lang->design->delete = 'Delete';
|
||||
$lang->design->confirmDelete = 'Do you want to delete this design?';
|
||||
$lang->design->edit = 'Edit';
|
||||
$lang->design->products = 'Linked Product';
|
||||
$lang->design->story = 'Linked Story';
|
||||
$lang->design->file = 'File';
|
||||
$lang->design->type = 'Type';
|
||||
$lang->design->name = 'Name';
|
||||
$lang->design->create = 'Create Design';
|
||||
$lang->design->view = 'View';
|
||||
$lang->design->desc = 'Description';
|
||||
$lang->design->product = 'Linked Product';
|
||||
$lang->design->basicInfo = 'Basic Information';
|
||||
$lang->design->commitDate = 'Committed Date';
|
||||
$lang->design->affectedStory = "{$lang->storyCommon}";
|
||||
$lang->design->affectedTasks = 'Task';
|
||||
$lang->design->submit = 'Submit Review';
|
||||
$lang->design->revision = 'Linked Code';
|
||||
$lang->design->designView = 'Details';
|
||||
$lang->design->reviewObject = 'Review Object';
|
||||
$lang->design->createdBy = 'CreatedBy';
|
||||
$lang->design->createdDate = 'CreatedDate';
|
||||
$lang->design->basicInfo = 'Basic Information';
|
||||
|
||||
$lang->design->typeList = array();
|
||||
$lang->design->typeList['HLDS'] = 'High-Level';
|
||||
$lang->design->typeList['DDS'] = 'Detailed';
|
||||
$lang->design->typeList['DBDS'] = 'Database';
|
||||
$lang->design->typeList['ADS'] = 'API';
|
||||
|
||||
$lang->design->range = 'Impact';
|
||||
$lang->design->errorSelection = 'No record selected!';
|
||||
$lang->design->noDesign = 'No record.';
|
||||
|
||||
$lang->design->rangeList = array();
|
||||
$lang->design->rangeList['all'] = 'All';
|
||||
$lang->design->rangeList['assign'] = 'Selected';
|
||||
|
||||
$lang->design->featureBar['all'] = 'All';
|
||||
$lang->design->featureBar += $lang->design->typeList;
|
||||
@@ -53,6 +53,10 @@ $lang->program->leftTasks = '剩余任务';
|
||||
$lang->program->leftBugs = '剩余Bug';
|
||||
$lang->program->children = '子项目';
|
||||
$lang->program->parent = '父项目';
|
||||
$lang->program->allStories = '总需求';
|
||||
$lang->program->doneStories = '已完成';
|
||||
$lang->program->leftStories = '剩余需求';
|
||||
$lang->program->allInput = '项目总投入';
|
||||
|
||||
$lang->program->unitList[''] = '';
|
||||
$lang->program->unitList['yuan'] = '元';
|
||||
|
||||
Reference in New Issue
Block a user