* Rewrite program product page.
This commit is contained in:
@@ -49,3 +49,8 @@ $config->product->statisticFields['plans'] = array('plans');
|
||||
$config->product->statisticFields['releases'] = array('releases');
|
||||
|
||||
$config->product->skipRedirectMethod = ',create,index,showerrornone,ajaxgetdropmenu,kanban,all,manageline,export,ajaxgetplans,';
|
||||
|
||||
$config->product->actionList['edit']['icon'] = 'edit';
|
||||
$config->product->actionList['edit']['text'] = $lang->edit;
|
||||
$config->product->actionList['edit']['hint'] = $lang->edit;
|
||||
$config->product->actionList['edit']['url'] = array('module' => 'product', 'method' => 'edit', 'params' => "productID={id}");
|
||||
|
||||
@@ -119,6 +119,14 @@ $config->product->dtable->fieldList['releases']['type'] = 'number';
|
||||
$config->product->dtable->fieldList['releases']['sortType'] = false;
|
||||
$config->product->dtable->fieldList['releases']['align'] = 'center';
|
||||
|
||||
$config->product->dtable->fieldList['actions']['name'] = 'actions';
|
||||
$config->product->dtable->fieldList['actions']['title'] = $lang->actions;
|
||||
$config->product->dtable->fieldList['actions']['type'] = 'actions';
|
||||
$config->product->dtable->fieldList['actions']['minWidth'] = '60';
|
||||
$config->product->dtable->fieldList['actions']['fixed'] = 'right';
|
||||
$config->product->dtable->fieldList['actions']['menu'] = array('edit');
|
||||
$config->product->dtable->fieldList['actions']['list'] = $config->product->actionList;
|
||||
|
||||
/* Default definition of WorkFlow extend fields. */
|
||||
$config->product->dtable->extendField['name'] = 'field';
|
||||
$config->product->dtable->extendField['title'] = 'name';
|
||||
|
||||
@@ -1669,4 +1669,47 @@ class productModel extends model
|
||||
$this->delete(TABLE_PRODUCT, $productID);
|
||||
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq(1)->where('product')->eq($productID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数据表格输出数据。
|
||||
* Format data for list.
|
||||
*
|
||||
* @param object $product
|
||||
* @param array $users
|
||||
* @param array $avatarList
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function formatDataForList(object $product, array $users, array $avatarList): object
|
||||
{
|
||||
$totalStories = $product->stories['finishClosed'] + $product->stories['unclosed'];
|
||||
$totalBugs = $product->unResolved + $product->fixedBugs;
|
||||
|
||||
$item = new stdClass();
|
||||
$item->name = $product->name;
|
||||
$item->id = $product->id;
|
||||
$item->type = 'product';
|
||||
$item->draftStories = $product->stories['draft'];
|
||||
$item->activeStories = $product->stories['active'];
|
||||
$item->changingStories = $product->stories['changing'];
|
||||
$item->reviewingStories = $product->stories['reviewing'];
|
||||
$item->storyCompleteRate = ($totalStories == 0 ? 0 : round($product->stories['finishClosed'] / $totalStories, 3) * 100);
|
||||
$item->unResolvedBugs = $product->unResolved;
|
||||
$item->bugFixedRate = ($totalBugs == 0 ? 0 : round($product->fixedBugs / $totalBugs, 3) * 100);
|
||||
$item->plans = $product->plans;
|
||||
$item->releases = $product->releases;
|
||||
$item->productLine = $product->lineName;
|
||||
$item->execution = $product->executions;
|
||||
$item->testCaseCoverage = $product->coverage;
|
||||
$item->actions = zget($product, 'actions', array());
|
||||
|
||||
if(!empty($product->PO))
|
||||
{
|
||||
$item->PO = zget($users, $product->PO);
|
||||
$item->POAvatar = zget($avatarList, $product->PO);
|
||||
$item->POAccount = $product->PO;
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
namespace zin;
|
||||
|
||||
/* Get column settings of the data table. */
|
||||
$cols = array_values($config->product->dtable->fieldList);
|
||||
$cols = $config->product->dtable->fieldList;
|
||||
|
||||
$extendFieldList = $this->product->getFlowExtendFields();
|
||||
foreach($extendFieldList as $field => $name)
|
||||
@@ -22,45 +22,15 @@ foreach($extendFieldList as $field => $name)
|
||||
$extCol['name'] = $field;
|
||||
$extCol['title'] = $name;
|
||||
|
||||
$cols[] = $extCol;
|
||||
$cols[$field] = $extCol;
|
||||
}
|
||||
|
||||
/* Closure function for generating table data. */
|
||||
$productStats = initTableData($productStats, $cols, $this->product);
|
||||
$fnGenerateTableData = function($productList) use($users, $avatarList)
|
||||
{
|
||||
$data = array();
|
||||
foreach($productList as $product)
|
||||
{
|
||||
$totalStories = $product->stories['finishClosed'] + $product->stories['unclosed'];
|
||||
$totalBugs = $product->unResolved + $product->fixedBugs;
|
||||
|
||||
$item = new stdClass();
|
||||
|
||||
if(!empty($product->PO))
|
||||
{
|
||||
$item->PO = zget($users, $product->PO);
|
||||
$item->POAvatar = $avatarList[$product->PO];
|
||||
$item->POAccount = $product->PO;
|
||||
}
|
||||
|
||||
$item->name = $product->name;
|
||||
$item->id = $product->id;
|
||||
$item->type = 'product';
|
||||
$item->draftStories = $product->stories['draft'];
|
||||
$item->activeStories = $product->stories['active'];
|
||||
$item->changingStories = $product->stories['changing'];
|
||||
$item->reviewingStories = $product->stories['reviewing'];
|
||||
$item->storyCompleteRate = ($totalStories == 0 ? 0 : round($product->stories['finishClosed'] / $totalStories, 3) * 100);
|
||||
$item->unResolvedBugs = $product->unResolved;
|
||||
$item->bugFixedRate = ($totalBugs == 0 ? 0 : round($product->fixedBugs / $totalBugs, 3) * 100);
|
||||
$item->plans = $product->plans;
|
||||
$item->releases = $product->releases;
|
||||
$item->productLine = $product->lineName;
|
||||
$item->execution = $product->executions;
|
||||
$item->testCaseCoverage = $product->coverage;
|
||||
|
||||
$data[] = $item;
|
||||
}
|
||||
foreach($productList as $product) $data[] = $this->product->formatDataForList($product, $users, $avatarList);
|
||||
|
||||
return $data;
|
||||
};
|
||||
|
||||
@@ -753,7 +753,8 @@ class program extends control
|
||||
$program = $this->program->getByID($programID);
|
||||
if(!$program) return print(js::error($this->lang->notFound) . js::locate('back'));
|
||||
|
||||
echo $this->fetch('program', 'product', "programID=$programID");
|
||||
if(common::hasPriv('program', 'product')) return $this->locate(inlink('product', "programID=$programID"));
|
||||
if(common::hasPriv('program', 'project')) return $this->locate(inlink('project', "programID=$programID"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace zin;
|
||||
|
||||
featureBar
|
||||
(
|
||||
set::current($browseType),
|
||||
set::linkParams("programID={$programID}&browseType={key}&orderBy=$orderBy"),
|
||||
);
|
||||
|
||||
toolbar
|
||||
(
|
||||
item(set
|
||||
(array(
|
||||
'text' => $lang->product->create,
|
||||
'icon' => 'plus',
|
||||
'class'=> 'btn primary',
|
||||
'url' => $this->createLink('product', 'create', "programID={$programID}")
|
||||
))),
|
||||
);
|
||||
|
||||
$cols = $this->config->product->dtable->fieldList;
|
||||
|
||||
$data = array();
|
||||
$products = initTableData($products, $cols, $this->product);
|
||||
foreach($products as $product) $data[] = $this->product->formatDataForList($product, $users, $usersAvatar);
|
||||
|
||||
$summary = sprintf($lang->product->pageSummary, count($data));
|
||||
$footToolbar = common::hasPriv('product', 'batchEdit') ? array('items' => array(array('text' => $lang->edit, 'class' => 'btn batch-btn size-sm primary', 'data-url' => $this->createLink('product', 'batchEdit', "programID={$programID}")))) : null;
|
||||
|
||||
dtable
|
||||
(
|
||||
set::userMap($users),
|
||||
set::cols($cols),
|
||||
set::data($data),
|
||||
set::nested(false),
|
||||
//set::onRenderCell(jsRaw('window.renderCell')),
|
||||
set::footToolbar($footToolbar),
|
||||
set::footPager(usePager()),
|
||||
set::footer(array('checkbox', 'toolbar', array('html' => $summary, 'className' => "text-dark"), 'flex', 'pager')),
|
||||
);
|
||||
|
||||
render();
|
||||
Reference in New Issue
Block a user