* Finish task #3807, 3831, 3833.
This commit is contained in:
@@ -12,3 +12,6 @@
|
||||
$config->block = new stdclass();
|
||||
$config->block->editor = new stdclass();
|
||||
$config->block->editor->set = array('id' => 'html', 'tools' => 'simple');
|
||||
|
||||
$config->statistic = new stdclass();
|
||||
$config->statistic->storyStages = array('wait', 'planned', 'developing', 'testing', 'released');
|
||||
|
||||
+43
-17
@@ -239,6 +239,12 @@ class block extends control
|
||||
$block->moreLink = $this->createLink('company', 'dynamic');
|
||||
}
|
||||
|
||||
$block->actionLink = '';
|
||||
if($block->block == 'overview' && common::hasPriv('product', 'create'))
|
||||
{
|
||||
$block->actionLink = html::a($this->createLink('product', 'create'), "<i class='icon icon-plus'> </i>" . $this->lang->product->create, '', "class='btn'");
|
||||
}
|
||||
|
||||
if($this->block->isLongBlock($block))
|
||||
{
|
||||
$longBlocks[$key] = $block;
|
||||
@@ -688,17 +694,18 @@ class block extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Print report block.
|
||||
* Print statistic block.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printReportBlock()
|
||||
public function printStatisticBlock()
|
||||
{
|
||||
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
|
||||
|
||||
$status = isset($this->params->type) ? $this->params->type : '';
|
||||
$orderBy = isset($this->params->type) ? $this->params->orderBy : 'id_asc';
|
||||
$num = isset($this->params->num) ? (int)$this->params->num : 0;
|
||||
|
||||
/* Get products. */
|
||||
$products = $this->loadModel('product')->getList($status);
|
||||
@@ -715,11 +722,11 @@ class block extends control
|
||||
$products = $this->dao->select('*')->from(TABLE_PRODUCT)
|
||||
->where('id')->in($productIDList)
|
||||
->orderBy($orderBy)
|
||||
->beginIF($this->viewType != 'json')->limit($num)->fi()
|
||||
->fetchAll('id');
|
||||
|
||||
/* Get stories. */
|
||||
$stories = $this->dao->select('product, stage, COUNT(status) AS count')
|
||||
->from(TABLE_STORY)
|
||||
$stories = $this->dao->select('product, stage, COUNT(status) AS count')->from(TABLE_STORY)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('product')->in($productIDList)
|
||||
->groupBy('product, stage')
|
||||
@@ -750,9 +757,9 @@ class block extends control
|
||||
if($plan->end >= helper::today()) $unexpired++;
|
||||
}
|
||||
|
||||
$plan = new stdclass;
|
||||
$plan->expired = $expired;
|
||||
$plan->unexpired = $unexpired;
|
||||
$plan = array();
|
||||
$plan['expired'] = $expired;
|
||||
$plan['unexpired'] = $unexpired;
|
||||
|
||||
$plans[$product] = $plan;
|
||||
}
|
||||
@@ -776,30 +783,49 @@ class block extends control
|
||||
if($project->status != 'done' && $project->status != 'closed' && $project->status != 'suspended' && $project->end < helper::today()) $delay++;
|
||||
}
|
||||
|
||||
$project = new stdclass();
|
||||
$project->doing = $doing;
|
||||
$project->done = $done;
|
||||
$project->delay = $delay;
|
||||
$project = array();
|
||||
$project['doing'] = $doing;
|
||||
$project['done'] = $done;
|
||||
$project['delay'] = $delay;
|
||||
|
||||
$projects[$product] = $project;
|
||||
}
|
||||
|
||||
/* Get releases. */
|
||||
$releases = $this->dao->select('product, COUNT(*) AS count')
|
||||
->from(TABLE_RELEASE)
|
||||
$releases = $this->dao->select('product, status, COUNT(*) AS count')->from(TABLE_RELEASE)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('product')->in($productIDList)
|
||||
->groupBy('product, status')
|
||||
->fetchGroup('product', 'status');
|
||||
foreach($releases as $product => $release)
|
||||
{
|
||||
$release['normal'] = isset($release['normal']) ? $release['normal']->count : 0;
|
||||
$release['terminate'] = isset($release['terminate']) ? $release['terminate']->count : 0;
|
||||
|
||||
$releases[$product] = $release;
|
||||
}
|
||||
|
||||
/* Get last releases. */
|
||||
$lastReleases = $this->dao->select('product, COUNT(*) AS count')->from(TABLE_RELEASE)
|
||||
->where('date')->eq(date('Y-m-d', strtotime('-1 day')))
|
||||
->andWhere('product')->in($productIDList)
|
||||
->groupBy('product')
|
||||
->fetchPairs();
|
||||
|
||||
foreach($products as $productID => $product)
|
||||
{
|
||||
$product->stories = isset($stories[$productID]) ? $stories[$productID] : 0;
|
||||
$product->plans = isset($plans[$productID]) ? $plans[$productID] : 0;
|
||||
$product->projects = isset($projects[$productID]) ? $projects[$productID] : 0;
|
||||
$product->releases = isset($releases[$productID]) ? $releases[$productID] : 0;
|
||||
$product->stories = isset($stories[$productID]) ? $stories[$productID] : 0;
|
||||
$product->plans = isset($plans[$productID]) ? $plans[$productID] : 0;
|
||||
$product->projects = isset($projects[$productID]) ? $projects[$productID] : 0;
|
||||
$product->releases = isset($releases[$productID]) ? $releases[$productID] : 0;
|
||||
$product->lastRelease = isset($lastReleases[$productID]) ? $lastReleases[$productID] : 0;
|
||||
}
|
||||
|
||||
$this->app->loadLang('story');
|
||||
$this->app->loadLang('productplan');
|
||||
$this->app->loadLang('project');
|
||||
$this->app->loadLang('release');
|
||||
|
||||
$this->view->products = $products;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,11 +57,12 @@ $lang->block->hidden = 'Hide';
|
||||
$lang->block->dynamicInfo = "<span class='timeline-tag'>%s</span>, <span class='timeline-text'>%s <em>%s</em> %s <a href='%s'>%s</a></span>";
|
||||
|
||||
$lang->block->default['product']['1']['title'] = $lang->productCommon . ' Report';
|
||||
$lang->block->default['product']['1']['block'] = 'report';
|
||||
$lang->block->default['product']['1']['block'] = 'statistic';
|
||||
$lang->block->default['product']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['product']['1']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['product']['1']['params']['type'] = 'noclosed';
|
||||
$lang->block->default['product']['1']['params']['num'] = 5;
|
||||
|
||||
$lang->block->default['product']['2']['title'] = $lang->productCommon . ' Overview';
|
||||
$lang->block->default['product']['2']['block'] = 'overview';
|
||||
@@ -223,12 +224,12 @@ $lang->block->moduleList['todo'] = 'Todo';
|
||||
|
||||
$lang->block->modules['product'] = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks->report = $lang->productCommon . ' Report';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Overview';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . 'List';
|
||||
$lang->block->modules['product']->availableBlocks->story = 'Stories';
|
||||
$lang->block->modules['product']->availableBlocks->plan = 'Plans';
|
||||
$lang->block->modules['product']->availableBlocks->release = 'Releases';
|
||||
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Report';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Overview';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . 'List';
|
||||
$lang->block->modules['product']->availableBlocks->story = 'Stories';
|
||||
$lang->block->modules['product']->availableBlocks->plan = 'Plans';
|
||||
$lang->block->modules['product']->availableBlocks->release = 'Releases';
|
||||
$lang->block->modules['project'] = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks->list = $lang->projectCommon . 'List';
|
||||
|
||||
@@ -57,11 +57,12 @@ $lang->block->hidden = '隐藏';
|
||||
$lang->block->dynamicInfo = "<span class='timeline-tag'>%s</span>, <span class='timeline-text'>%s <em>%s</em> %s <a href='%s'>%s</a></span>";
|
||||
|
||||
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
|
||||
$lang->block->default['product']['1']['block'] = 'report';
|
||||
$lang->block->default['product']['1']['block'] = 'statistic';
|
||||
$lang->block->default['product']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['product']['1']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['product']['1']['params']['type'] = 'noclosed';
|
||||
$lang->block->default['product']['1']['params']['num'] = 5;
|
||||
|
||||
$lang->block->default['product']['2']['title'] = $lang->productCommon . '总览';
|
||||
$lang->block->default['product']['2']['block'] = 'overview';
|
||||
@@ -223,12 +224,12 @@ $lang->block->moduleList['todo'] = '待办';
|
||||
|
||||
$lang->block->modules['product'] = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks->report = $lang->productCommon . '统计';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . '总览';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
|
||||
$lang->block->modules['product']->availableBlocks->story = '需求列表';
|
||||
$lang->block->modules['product']->availableBlocks->plan = '计划列表';
|
||||
$lang->block->modules['product']->availableBlocks->release = '发布列表';
|
||||
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . '统计';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . '总览';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
|
||||
$lang->block->modules['product']->availableBlocks->story = '需求列表';
|
||||
$lang->block->modules['product']->availableBlocks->plan = '计划列表';
|
||||
$lang->block->modules['product']->availableBlocks->release = '发布列表';
|
||||
$lang->block->modules['project'] = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks->list = $lang->projectCommon . '列表';
|
||||
|
||||
@@ -57,11 +57,12 @@ $lang->block->hidden = '隱藏';
|
||||
$lang->block->dynamicInfo = "<span class='timeline-tag'>%s</span>, <span class='timeline-text'>%s <em>%s</em> %s <a href='%s'>%s</a></span>";
|
||||
|
||||
$lang->block->default['product']['1']['title'] = $lang->productCommon . '統計';
|
||||
$lang->block->default['product']['1']['block'] = 'report';
|
||||
$lang->block->default['product']['1']['block'] = 'statistic';
|
||||
$lang->block->default['product']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['product']['1']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['product']['1']['params']['type'] = 'noclosed';
|
||||
$lang->block->default['product']['1']['params']['num'] = 5;
|
||||
|
||||
$lang->block->default['product']['2']['title'] = $lang->productCommon . '總覽';
|
||||
$lang->block->default['product']['2']['block'] = 'overview';
|
||||
@@ -223,12 +224,12 @@ $lang->block->moduleList['todo'] = '待辦';
|
||||
|
||||
$lang->block->modules['product'] = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['product']->availableBlocks->report = $lang->productCommon . '統計';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . '總覽';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
|
||||
$lang->block->modules['product']->availableBlocks->story = '需求列表';
|
||||
$lang->block->modules['product']->availableBlocks->plan = '計劃列表';
|
||||
$lang->block->modules['product']->availableBlocks->release = '發佈列表';
|
||||
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . '統計';
|
||||
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . '總覽';
|
||||
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
|
||||
$lang->block->modules['product']->availableBlocks->story = '需求列表';
|
||||
$lang->block->modules['product']->availableBlocks->plan = '計劃列表';
|
||||
$lang->block->modules['product']->availableBlocks->release = '發佈列表';
|
||||
$lang->block->modules['project'] = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks = new stdclass();
|
||||
$lang->block->modules['project']->availableBlocks->list = $lang->projectCommon . '列表';
|
||||
|
||||
@@ -394,12 +394,12 @@ class blockModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product report params.
|
||||
* Get product statistic params.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getReportParams()
|
||||
public function getStatisticParams()
|
||||
{
|
||||
$params = new stdclass();
|
||||
$params->type['name'] = $this->lang->block->type;
|
||||
@@ -411,7 +411,7 @@ class blockModel extends model
|
||||
$params->orderBy['options'] = $this->lang->block->orderByList->product;
|
||||
$params->orderBy['control'] = 'select';
|
||||
|
||||
return json_encode($params);
|
||||
return json_encode($this->onlyNumParams($params));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,15 +25,14 @@ $useGuest = $this->app->user->account == 'guest';
|
||||
<div class='row'>
|
||||
<div class='col-sm-12'>
|
||||
<div class='panel block-<?php echo $block->block;?> <?php if(isset($block->params->color)) echo 'panel-' . $block->params->color;?>' id='block<?php echo $block->id?>' data-id='<?php echo $block->id?>' data-name='<?php echo $block->title?>'>
|
||||
<?php $hasHeading = ($block->block != 'welcome' and $block->block != 'flowchart');?>
|
||||
<?php $hasHeading = ($block->block != 'welcome' and $block->block != 'flowchart' and $block->block != 'statistic');?>
|
||||
<?php if($hasHeading):?>
|
||||
<div class='panel-heading'>
|
||||
<div class='panel-title'><?php echo $block->title;?></div>
|
||||
<?php endif;?>
|
||||
<nav class='panel-actions nav nav-default'>
|
||||
<?php if(!empty($block->moreLink)):?>
|
||||
<?php echo '<li>' . html::a($block->moreLink, 'MORE', '', "title='{$lang->more}'") . '</li>'; ?>
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($block->actionLink)) echo '<li>' . $block->actionLink . '</li>';?>
|
||||
<?php if(!empty($block->moreLink)) echo '<li>' . html::a($block->moreLink, 'MORE', '', "title='{$lang->more}'") . '</li>'; ?>
|
||||
<li class='dropdown'>
|
||||
<a href='javascript:;' data-toggle='dropdown' class='panel-action'><i class='icon icon-ellipsis-v'></i></a>
|
||||
<ul class='dropdown-menu pull-right'>
|
||||
@@ -71,9 +70,8 @@ $useGuest = $this->app->user->account == 'guest';
|
||||
<div class='panel-title'><?php echo $block->title;?></div>
|
||||
<?php endif;?>
|
||||
<nav class='panel-actions nav nav-default'>
|
||||
<?php if(!empty($block->moreLink)):?>
|
||||
<?php echo '<li>' . html::a($block->moreLink, 'MORE', '', "title='{$lang->more}'") . '</li>';?>
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($block->actionLink)) echo '<li>' . $block->actionLink . '</li>';?>
|
||||
<?php if(!empty($block->moreLink)) echo '<li>' . html::a($block->moreLink, 'MORE', '', "title='{$lang->more}'") . '</li>';?>
|
||||
<li class='dropdown'>
|
||||
<a href='javascript:;' data-toggle='dropdown' class='panel-action'><i class='icon icon-ellipsis-v'></i></a>
|
||||
<ul class='dropdown-menu pull-right'>
|
||||
|
||||
@@ -10,8 +10,29 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<div class='panel-body has-table'>
|
||||
<?php echo $lang->product->all . $total;?>
|
||||
<?php echo $lang->product->statusList['normal'] . $normal;?>
|
||||
<?php echo $lang->product->statusList['closed'] . $closed;?>
|
||||
<style>
|
||||
.block-overview .status-list li + li {margin-top: 5px;}
|
||||
.block-overview .status-list li > strong {font-size: 16px;}
|
||||
.block-overview .panel-body {padding: 25px 0;}
|
||||
.progress-pie {position: relative;}
|
||||
.progress-pie .progress-info {position: absolute; width: 100%; height: 100%; left: 0; top: 0; text-align: center; padding-top: 25px;}
|
||||
.progress-pie .progress-info > small {display: block; color: #A6AAB8; line-height: 14px;}
|
||||
.progress-pie .progress-info > strong {display: block; font-size: 36px; line-height: 40px;}
|
||||
</style>
|
||||
<div class="panel-body table-row">
|
||||
<div class="col-6 text-middle text-center">
|
||||
<div class="progress-pie inline-block" data-value="72" data-doughnut-size="80">
|
||||
<canvas width="100" height="100" style="width: 100px; height: 100px;"></canvas>
|
||||
<div class="progress-info">
|
||||
<small><?php echo $lang->product->all;?></small>
|
||||
<strong><?php echo $total;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 text-middle">
|
||||
<ul class="list-unstyled status-list">
|
||||
<li><span class="status-unclosed"><span class="label label-dot"></span> <?php echo $lang->product->statusList['normal'];?></span> <strong><?php echo $normal;?></strong></li>
|
||||
<li><span class="status-closed"><span class="label label-dot"></span> <?php echo $lang->product->statusList['closed'];?></span> <strong><?php echo $closed;?></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The report block view file of block module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package block
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
$this->loadModel('story');
|
||||
?>
|
||||
<div class="panel-body has-table">
|
||||
<ul class='nav nav-secondary nav-product-report'>
|
||||
<?php foreach($products as $product):?>
|
||||
<li><?php echo html::a('###', $product->name, "data-id='$product->id'");?></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
<?php foreach($products as $product):?>
|
||||
<div class='div-product-report' id='productReport<?php echo $product->id;?>'>
|
||||
<div class='col-md-6'>
|
||||
<label class='storyCount text-lg'><?php echo count($product->stories);?></li>
|
||||
<?php foreach($config->product->report->stageLabels as $stage):?>
|
||||
<dl>
|
||||
<dt><?php echo zget($product->stories, $stage, '0');?></dt>
|
||||
<dd><?php echo zget($lang->story->stageList, $stage, '0');?></dd>
|
||||
</dl>
|
||||
<?php endforeach;?>
|
||||
</ol>
|
||||
</div>
|
||||
<div class='col-md-6'>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* The report block view file of block module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package block
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<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; padding: 10px 10px 10px 200px;}
|
||||
.product-info + .product-info {margin-top: 10px;}
|
||||
.product-info .progress {position: absolute; left: 10px; top: 35px; width: 180px;}
|
||||
.product-info .progress-info {position: absolute; left: 8px; top: 10px; width: 180px; font-size: 12px;}
|
||||
.product-info .type-info {color: #A6AAB8; text-align: center;}
|
||||
.product-info .type-label {font-size: 12px;}
|
||||
.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 .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-left: 1px solid #EBF2FB; width: 260px; padding-left: 0;}
|
||||
.block-statistic .nav-secondary > li > a {font-size: 16px; 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.active > a {font-size: 20px; color: #3C4353; background: transparent; box-shadow: none;}
|
||||
.block-statistic .nav-secondary > li.active > a:hover,
|
||||
.block-statistic .nav-secondary > li.active > a:focus,
|
||||
.block-statistic .nav-secondary > li > a:hover {box-shadow: none;}
|
||||
.block-statistic .nav-secondary > li.active > a:before {content: ' '; display: block; left: -1px; top: 10px; bottom: 10px; width: 4px; background: #006af1; position: absolute;}
|
||||
</style>
|
||||
<div class="panel-body">
|
||||
<div class="table-row">
|
||||
<div class="col tab-content">
|
||||
<?php foreach($products as $product):?>
|
||||
<div class="tab-pane fade <?php if($product == reset($products)) echo 'active';?> in" id="tab<?php echo $product->code;?>">
|
||||
<div class="table-row">
|
||||
<div class="col-6 text-middle">
|
||||
<div class="tile">
|
||||
<div class="tile-title"><?php echo $lang->story->total;?></div>
|
||||
<?php if($product->stories):?>
|
||||
<div class="tile-amount"><?php echo array_sum($product->stories);?></div>
|
||||
<?php common::printLink('product', 'browse', "productID={$product->id}", $lang->story->viewAll . '<span class="label label-badge label-icon"><i class="icon icon-arrow-right"></i></span>', '', 'class="btn btn-primary btn-circle btn-icon-right btn-sm"');?>
|
||||
<?php else:?>
|
||||
<div class="tile-amount">0</div>
|
||||
<?php common::printLink('story', 'create', "productID={$product->id}", '<span class="label label-badge label-icon"><i class="icon icon-plus"></i></span>' . $lang->story->create, '', 'class="btn btn-primary btn-circle btn-icon-left btn-sm"');?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<ul class="types-line">
|
||||
<?php foreach($config->statistic->storyStages as $stage):?>
|
||||
<li>
|
||||
<div>
|
||||
<small><?php echo zget($lang->story->stageList, $stage);?></small>
|
||||
<span><?php echo $product->stories ? zget($product->stories, $stage, 0) : 0;?></span>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php if($product->stories):?>
|
||||
<div class="col-6">
|
||||
<div class="product-info">
|
||||
<?php $totalPlan = $product->plans ? array_sum($product->plans) : 0;?>
|
||||
<?php $unexpiredPlan = $product->plans ? zget($product->plans, 'unexpired', 0) : 0;?>
|
||||
<?php $unexpiredRate = $totalPlan ? round($unexpiredPlan / $totalPlan * 100, 2) : 0;?>
|
||||
<?php if($totalPlan):?>
|
||||
<div class="progress-info"></div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="<?php echo $unexpiredRate;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $unexpiredRate;?>%"></div>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="actions">
|
||||
<?php common::printLink('productplan', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i>" . $lang->productplan->create, '', "class='btn btn-info'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="type-info">
|
||||
<div class="type-label">
|
||||
<span><?php echo $lang->story->planAB;?></span> / <span><?php echo $lang->productplan->featureBar['browse']['unexpired'];?></span>
|
||||
</div>
|
||||
<div class="type-value">
|
||||
<small><?php echo $totalPlan;?></small> / <strong><?php echo $unexpiredPlan;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<?php $totalProject = $product->projects ? array_sum($product->projects) : 0;?>
|
||||
<?php $doingProject = $product->projects ? zget($product->projects, 'doing', 0) : 0;?>
|
||||
<?php $delayProject = $product->projects ? zget($product->projects, 'delay', 0) : 0;?>
|
||||
<?php $doingRate = $totalProject ? round($doingProject / $totalProject * 100, 2) : 0;?>
|
||||
<?php if($totalProject):?>
|
||||
<div class="progress-info">
|
||||
<?php if($delayProject):?>
|
||||
<i class="icon icon-exclamation-sign text-danger icon-sm"></i> <span class="text-muted"><?php echo $lang->project->delayed;?></span> <strong><?php echo $delayProject;?></strong>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="<?php echo $doingRate;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $doingRate;?>%"></div>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="actions">
|
||||
<?php common::printLink('project', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i>" . $lang->project->create, '', "class='btn btn-info'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="type-info">
|
||||
<div class="type-label">
|
||||
<span><?php echo $lang->projectCommon;?></span> / <span><?php echo $lang->project->statusList['doing'];?></span>
|
||||
</div>
|
||||
<div class="type-value">
|
||||
<small><?php echo $totalProject;?></small> / <strong><?php echo $doingProject;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<?php $totalRelease = $product->releases ? array_sum($product->releases) : 0;?>
|
||||
<?php $normalRelease = $product->releases ? zget($product->releases, 'normal', 0) : 0;?>
|
||||
<?php $normalRate = $totalRelease ? round($normalRelease / $totalRelease * 100, 2) : 0;?>
|
||||
<?php if($totalRelease):?>
|
||||
<div class="progress-info">
|
||||
<?php if($product->lastRelease):?>
|
||||
<i class="icon icon-check-circle text-success icon-sm"></i> <span class="text-muted"><?php echo $lang->release->yesterday;?></span> <strong><?php echo $product->lastRelease;?></strong>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="<?php echo $normalRate;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $normalRate;?>%"></div>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="actions">
|
||||
<?php common::printLink('release', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i>" . $lang->release->create, '', "class='btn btn-info'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="type-info">
|
||||
<div class="type-label">
|
||||
<span><?php echo $lang->release->common;?></span> / <span><?php echo $lang->release->statusList['normal'];?></span>
|
||||
</div>
|
||||
<div class="type-value">
|
||||
<small><?php echo $totalRelease;?></small> / <strong><?php echo $normalRelease;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<div class="col col-nav">
|
||||
<ul class="nav nav-stacked nav-secondary">
|
||||
<?php foreach($products as $product):?>
|
||||
<li <?php if($product == reset($products)) echo "class='active'";?>><a href="javascript:;" data-target="#tab<?php echo $product->code;?>" data-toggle="tab" title='<?php echo $product->name;?>'><?php echo $product->name;?></a></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,4 +18,4 @@ a.removeModule:hover{color:red}
|
||||
tbody > tr > td > .btn-icon {margin-right: 3px;}
|
||||
|
||||
.noModule {margin-bottom: 10px;}
|
||||
.noStory {text-align: center; margin-top: 40px; font-size: 1.5em;}
|
||||
.noStory {text-align: center; margin-top: 40px;}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.noProduct {text-align: center; margin-top: 40px;}
|
||||
@@ -117,7 +117,8 @@ $lang->product->aclList['custom'] = 'Custom (Team members and Whitelist members
|
||||
$lang->product->storySummary = " <strong>%s</strong> Story(ies), <strong>%s</strong> hour(s) estimated, case coverage is <strong>%s</strong> on this page.";
|
||||
$lang->product->checkedSummary = " <strong>%total%</strong> Checked, <strong>%estimate%</strong> hour(s) estimated, case coverage is <strong>%rate%</strong>.";
|
||||
$lang->product->noModule = 'You have no modules<br/>Manage now';
|
||||
$lang->product->noStory = 'No records. You could ';
|
||||
$lang->product->noProduct = 'No product. You could ';
|
||||
$lang->product->noStory = 'No story. You could ';
|
||||
$lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
|
||||
@@ -117,7 +117,8 @@ $lang->product->aclList['custom'] = '自定义白名单(团队成员和白名
|
||||
$lang->product->storySummary = "本页共 <strong>%s</strong> 个需求,预计 <strong>%s</strong> 个工时,用例覆盖率<strong>%s</strong>。";
|
||||
$lang->product->checkedSummary = "选中 <strong>%total%</strong> 个需求,预计 <strong>%estimate%</strong> 个工时,用例覆盖率<strong>%rate%</strong>。";
|
||||
$lang->product->noModule = '您现在还没有模块信息<br/>请维护产品模块';
|
||||
$lang->product->noStory = '暂时没有记录,您现在可以';
|
||||
$lang->product->noProduct = '暂时没有产品,您现在可以';
|
||||
$lang->product->noStory = '暂时没有需求,您现在可以';
|
||||
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
|
||||
@@ -117,7 +117,8 @@ $lang->product->aclList['custom'] = '自定義白名單(團隊成員和白名
|
||||
$lang->product->storySummary = "本頁共 <strong>%s</strong> 個需求,預計 <strong>%s</strong> 個工時,用例覆蓋率<strong>%s</strong>。";
|
||||
$lang->product->checkedSummary = "選中 <strong>%total%</strong> 個需求,預計 <strong>%estimate%</strong> 個工時,用例覆蓋率<strong>%rate%</strong>。";
|
||||
$lang->product->noModule = '您現在還沒有模組信息<br/>請維護產品模組';
|
||||
$lang->product->noStory = '暫時沒有記錄,您現在可以';
|
||||
$lang->product->noProduct = '暫時沒有產品,您現在可以';
|
||||
$lang->product->noStory = '暫時沒有需求,您現在可以';
|
||||
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
|
||||
@@ -252,8 +252,8 @@ class productModel extends model
|
||||
->orWhere('createdBy')->eq($this->app->user->account)
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->beginIF($limit > 0)->limit($limit)->fi()
|
||||
->orderBy('`order` desc')
|
||||
->beginIF($limit > 0)->limit($limit)->fi()
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,14 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php if(empty($products)):?>
|
||||
<div class='noProduct'>
|
||||
<span class='text-muted'><?php echo $lang->product->noProduct;?></span>
|
||||
<strong><?php common::printLink('product', 'create', '', $lang->product->create);?></strong>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<?php echo $this->fetch('block', 'dashboard', 'module=product');?>
|
||||
<?php endif;?>
|
||||
<script>
|
||||
<?php if($this->config->product->homepage != 'index'):?>
|
||||
$(function()
|
||||
|
||||
@@ -22,6 +22,7 @@ $lang->project->to = '至';
|
||||
$lang->project->days = '可用工作日';
|
||||
$lang->project->day = '天';
|
||||
$lang->project->workHour = '工時';
|
||||
$lang->project->totalHours = '可用工時';
|
||||
$lang->project->status = $lang->projectCommon . '狀態';
|
||||
$lang->project->desc = $lang->projectCommon . '描述';
|
||||
$lang->project->owner = '負責人';
|
||||
@@ -29,6 +30,8 @@ $lang->project->PO = $lang->productCommon . '負責人';
|
||||
$lang->project->PM = $lang->projectCommon . '負責人';
|
||||
$lang->project->QD = '測試負責人';
|
||||
$lang->project->RD = '發佈負責人';
|
||||
$lang->project->qa = '測試';
|
||||
$lang->project->release = '發佈';
|
||||
$lang->project->acl = '訪問控制';
|
||||
$lang->project->teamname = '團隊名稱';
|
||||
$lang->project->order = $lang->projectCommon . '排序';
|
||||
@@ -106,6 +109,7 @@ $lang->project->groupTask = '分組瀏覽任務';
|
||||
$lang->project->story = '需求列表';
|
||||
$lang->project->bug = 'Bug列表';
|
||||
$lang->project->dynamic = '動態';
|
||||
$lang->project->latestDynamic = '最新動態';
|
||||
$lang->project->build = '版本列表';
|
||||
$lang->project->testtask = '測試任務';
|
||||
$lang->project->burn = '燃盡圖';
|
||||
@@ -141,6 +145,8 @@ $lang->project->tree = '樹狀圖';
|
||||
$lang->project->storyKanban = '需求看板';
|
||||
$lang->project->storySort = '需求排序';
|
||||
$lang->project->importPlanStory = '創建' . $lang->projectCommon . '成功!\n是否導入計劃關聯的相關需求?';
|
||||
$lang->project->iteration = '版本迭代';
|
||||
$lang->project->iterationInfo = '迭代%s次';
|
||||
|
||||
/* 分組瀏覽。*/
|
||||
$lang->project->allTasks = '所有';
|
||||
|
||||
@@ -48,6 +48,7 @@ $lang->release->finishStories = 'Finished %s Story';
|
||||
$lang->release->resolvedBugs = 'Solved %s Bug';
|
||||
$lang->release->createdBugs = 'Generated %s Bug';
|
||||
$lang->release->export = 'Export as HTML';
|
||||
$lang->release->yesterday = 'Released Yesterday';
|
||||
|
||||
$lang->release->filePath = 'Download : ';
|
||||
$lang->release->scmPath = 'SCM Path : ';
|
||||
|
||||
@@ -48,6 +48,7 @@ $lang->release->finishStories = '本次共完成 %s 个需求';
|
||||
$lang->release->resolvedBugs = '本次共解决 %s 个Bug';
|
||||
$lang->release->createdBugs = '本次共遗留 %s 个Bug';
|
||||
$lang->release->export = '导出HTML';
|
||||
$lang->release->yesterday = '昨日发布';
|
||||
|
||||
$lang->release->filePath = '下载地址:';
|
||||
$lang->release->scmPath = '版本库地址:';
|
||||
|
||||
@@ -48,6 +48,7 @@ $lang->release->finishStories = '本次共完成 %s 個需求';
|
||||
$lang->release->resolvedBugs = '本次共解決 %s 個Bug';
|
||||
$lang->release->createdBugs = '本次共遺留 %s 個Bug';
|
||||
$lang->release->export = '導出HTML';
|
||||
$lang->release->yesterday = '昨日發佈';
|
||||
|
||||
$lang->release->filePath = '下載地址:';
|
||||
$lang->release->scmPath = '版本庫地址:';
|
||||
|
||||
@@ -44,6 +44,7 @@ $lang->story->batchChangeBranch = "Batch Change Branches";
|
||||
$lang->story->batchChangeStage = "Batch Change Stages";
|
||||
$lang->story->batchAssignTo = "Batch Assign";
|
||||
$lang->story->batchChangeModule = "Batch Change Modules";
|
||||
$lang->story->viewAll = "View All";
|
||||
|
||||
$lang->story->common = 'Story';
|
||||
$lang->story->id = 'ID';
|
||||
@@ -91,6 +92,7 @@ $lang->story->newStory = 'Continue adding Story.';
|
||||
$lang->story->colorTag = 'Color Tag';
|
||||
$lang->story->files = 'Files';
|
||||
$lang->story->copy = "Duplicate a Story";
|
||||
$lang->story->total = "Total Stories";
|
||||
|
||||
$lang->story->ditto = 'Ditto';
|
||||
$lang->story->dittoNotice = 'This Story does not belong to the same Product as the last Story does!';
|
||||
|
||||
@@ -45,6 +45,7 @@ $lang->story->batchChangeBranch = "批量修改分支";
|
||||
$lang->story->batchChangeStage = "批量修改阶段";
|
||||
$lang->story->batchAssignTo = "批量指派";
|
||||
$lang->story->batchChangeModule = "批量修改模块";
|
||||
$lang->story->viewAll = '查看全部';
|
||||
|
||||
$lang->story->common = '需求';
|
||||
$lang->story->id = '编号';
|
||||
@@ -92,6 +93,7 @@ $lang->story->newStory = '继续添加需求';
|
||||
$lang->story->colorTag = '颜色标签';
|
||||
$lang->story->files = '附件';
|
||||
$lang->story->copy = "复制需求";
|
||||
$lang->story->total = '总需求';
|
||||
|
||||
$lang->story->ditto = '同上';
|
||||
$lang->story->dittoNotice = '该需求与上一需求不属于同一产品!';
|
||||
|
||||
@@ -45,6 +45,7 @@ $lang->story->batchChangeBranch = "批量修改分支";
|
||||
$lang->story->batchChangeStage = "批量修改階段";
|
||||
$lang->story->batchAssignTo = "批量指派";
|
||||
$lang->story->batchChangeModule = "批量修改模組";
|
||||
$lang->story->viewAll = '查看全部';
|
||||
|
||||
$lang->story->common = '需求';
|
||||
$lang->story->id = '編號';
|
||||
@@ -92,6 +93,7 @@ $lang->story->newStory = '繼續添加需求';
|
||||
$lang->story->colorTag = '顏色標籤';
|
||||
$lang->story->files = '附件';
|
||||
$lang->story->copy = "複製需求";
|
||||
$lang->story->total = '總需求';
|
||||
|
||||
$lang->story->ditto = '同上';
|
||||
$lang->story->dittoNotice = '該需求與上一需求不屬於同一產品!';
|
||||
|
||||
@@ -32,7 +32,7 @@ $lang->tree->manageBugChild = '維護Bug子模組';
|
||||
$lang->tree->manageCaseChild = '維護用例子模組';
|
||||
$lang->tree->manageCaselibChild = '維護測試庫子模組';
|
||||
$lang->tree->manageTaskChild = "維護{$lang->projectCommon}子模組";
|
||||
$lang->tree->syncFromProduct = '複製';
|
||||
$lang->tree->syncFromProduct = '複製模組';
|
||||
$lang->tree->dragAndSort = "拖放排序";
|
||||
$lang->tree->sort = "排序";
|
||||
$lang->tree->addChild = "增加子模組";
|
||||
|
||||
+5
-5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user