This commit is contained in:
daitingting
2018-04-23 15:55:39 +08:00
25 changed files with 299 additions and 96 deletions
+3
View File
@@ -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
View File
@@ -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;
}
+8 -7
View File
@@ -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';
+8 -7
View File
@@ -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 . '列表';
+8 -7
View File
@@ -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 . '列表';
+3 -3
View File
@@ -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));
}
/**
+5 -7
View File
@@ -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'>
+25 -4
View File
@@ -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> &nbsp; <strong><?php echo $normal;?></strong></li>
<li><span class="status-closed"><span class="label label-dot"></span> <?php echo $lang->product->statusList['closed'];?></span> &nbsp; <strong><?php echo $closed;?></strong></li>
</ul>
</div>
</div>
-38
View File
@@ -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>
+164
View File
@@ -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>
+1 -1
View File
@@ -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;}
+1
View File
@@ -0,0 +1 @@
.noProduct {text-align: center; margin-top: 40px;}
+2 -1
View File
@@ -118,7 +118,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 = '<div>You have no modules</div><div>Manage now</div>';
$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;
+2 -1
View File
@@ -118,7 +118,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 = '<div>您现在还没有模块信息</div><div>请维护产品模块</div>';
$lang->product->noStory = '暂时没有记录,您现在可以';
$lang->product->noProduct = '暂时没有产品,您现在可以';
$lang->product->noStory = '暂时没有需求,您现在可以';
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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');
}
+7
View File
@@ -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()
+6
View File
@@ -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 = '所有';
+1
View File
@@ -49,6 +49,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 : ';
+1
View File
@@ -49,6 +49,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 = '版本库地址:';
+1
View File
@@ -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 = '版本庫地址:';
+2
View File
@@ -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!';
+2
View File
@@ -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 = '该需求与上一需求不属于同一产品!';
+2
View File
@@ -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 = '該需求與上一需求不屬於同一產品!';
+1 -1
View File
@@ -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 = "增加子模組";