* [task#137010,done,3h] Add product release block.

This commit is contained in:
daitingting
2025-02-07 15:31:37 +08:00
committed by 谢杞钰
parent f7171d8db4
commit 65ecca8184
5 changed files with 161 additions and 14 deletions
+1 -1
View File
@@ -141,7 +141,7 @@ $config->doc->zentaoList['bug']['subMenu'][] = array('key' => 'productBug', 'nam
$config->doc->zentaoList['bug']['subMenu'][] = array('key' => 'planBug', 'name' => $lang->doc->zentaoList['planBug'] . $lang->doc->list, 'icon' => 'productplan', 'module' => 'productplan', 'method' => 'bug', 'params' => 'productID=0&planID=0&blockID=0', 'priv' => 'productplanView');
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productPlan', 'name' => $lang->doc->zentaoList['productPlan'] . $lang->doc->list, 'icon' => 'productplan', 'module' => 'productplan', 'method' => 'browse', 'params' => 'productID=0&branch=&browseType=undone&queryID=0&orderBy=begin_desc&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'productplanBrowse');
//$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productRelease', 'name' => $lang->doc->zentaoList['productRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'product', 'method' => 'browse', 'params' => '', 'priv' => 'releaseBrowse');
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productRelease', 'name' => $lang->doc->zentaoList['productRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'release', 'method' => 'browse', 'params' => 'productID=0&branch=all&type=all&orderBy=&param=0&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'releaseBrowse');
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'ER', 'name' => $lang->doc->zentaoList['ER'] . $lang->doc->list, 'icon' => 'lightbulb-alt', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=&param=0&storyType=epic&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'epicBrowse');
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'UR', 'name' => $lang->doc->zentaoList['UR'] . $lang->doc->list, 'icon' => 'customer', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=&param=0&storyType=requirement&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'requirementBrowse');
+30 -5
View File
@@ -26,9 +26,9 @@ class release extends control
$this->loadModel('product')->setMenu($productID, $branch);
$product = $this->product->getById($productID);
$products = $this->product->getPairs('all', 0, '', 'all');
if(empty($product)) $this->locate($this->createLink('product', 'create'));
$products = $this->product->getPairs('all', 0, '', 'all');
$this->product->checkAccess($productID, $products);
$this->view->product = $product;
@@ -48,20 +48,35 @@ class release extends control
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @param string $from
* @param int $blockID
* @access public
* @return void
*/
public function browse(int $productID, string $branch = 'all', string $type = 'all', string $orderBy = 't1.date_desc', string $param = '', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1)
public function browse(int $productID, string $branch = 'all', string $type = 'all', string $orderBy = 't1.date_desc', string $param = '', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $from = 'product', int $blockID = 0)
{
if($from === 'doc')
{
$this->app->loadLang('doc');
$products = $this->loadModel('product')->getPairs('all', 0, '', 'all');
if(empty($products)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->tips->noProduct));
if(!$productID) $productID = key($products);
$this->view->products = $products;
}
$this->commonAction($productID, $branch);
$this->app->loadClass('pager', true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->commonAction($productID, $branch);
$uri = $this->app->getURI(true);
$this->session->set('releaseList', $uri, 'product');
$this->session->set('buildList', $uri);
$showBranch = $this->view->product->type != 'normal';
$showBranch = $this->view->product->type != 'normal';
if(!$showBranch)
{
unset($this->config->release->dtable->fieldList['branch']);
@@ -73,7 +88,7 @@ class release extends control
if(strpos($sort, 'branchName_') !== false) $sort = str_replace('branchName_', 'branch_', $sort);
$queryID = $type == 'bySearch' ? (int)$param : 0;
$actionURL = $this->createLink('release', 'browse', "productID={$productID}&branch={$branch}&type=bySearch&orderBy={$sort}&param=myQueryID");
$actionURL = $this->createLink('release', 'browse', "productID={$productID}&branch={$branch}&type=bySearch&orderBy={$sort}&param=myQueryID&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&from=$from&blockID=$blockID");
$this->releaseZen->buildSearchForm($queryID, $actionURL, $this->view->product, $branch);
$releaseQuery = $type == 'bySearch' ? $this->releaseZen->getSearchQuery($queryID) : '';
@@ -94,6 +109,16 @@ class release extends control
$this->view->branchPairs = $this->loadModel('branch')->getPairs($productID);
$this->view->appList = $this->loadModel('system')->getPairs();
$this->view->childReleases = $this->release->getListByCondition(explode(',', $children), 0, true);
$this->view->from = $from;
$this->view->blockID = $blockID;
$this->view->idList = '';
if($from === 'doc')
{
$content = $this->loadModel('doc')->getDocBlockContent($blockID);
$this->view->idList = zget($content, 'idList', '');
}
$this->display();
}
+1
View File
@@ -1 +1,2 @@
.red{color: red;}
.mb-4-important{margin-bottom: 12px!important}
+39
View File
@@ -46,3 +46,42 @@ window.getCellSpan = function(cell)
return {rowSpan: cell.row.data.rowspan};
}
}
window.insertListToDoc = function()
{
const dtable = zui.DTable.query($('#releases'));
const checkedList = dtable.$.getChecks();
if(!checkedList.length) return;
let {cols, data} = dtable.options;
data = data.filter((item) => checkedList.includes(item.id + ''));
const docID = getDocApp()?.docID;
const blockType = 'productRelease';
const url = $.createLink('doc', 'buildZentaoList', `docID=${docID}&type=${blockType}&blockID=${blockID}`);
const formData = new FormData();
formData.append('cols', JSON.stringify(cols));
formData.append('data', JSON.stringify(data));
formData.append('idList', checkedList.join(','));
formData.append('url', insertListLink);
$.post(url, formData, function(resp)
{
resp = JSON.parse(resp);
if(resp.result == 'success')
{
const oldBlockID = resp.oldBlockID;
const newBlockID = resp.newBlockID;
zui.Modal.hide();
window.insertZentaoList && window.insertZentaoList(blockType, newBlockID, null, oldBlockID);
}
});
}
window.firstRendered = false;
window.toggleCheckRows = function(idList)
{
if(!idList?.length || firstRendered) return;
firstRendered = true;
const dtable = zui.DTable.query($('#releases'));
dtable.$.toggleCheckRows(idList.split(','), true);
}
+90 -8
View File
@@ -10,16 +10,79 @@ declare(strict_types=1);
*/
namespace zin;
dropmenu();
$isFromDoc = $from == 'doc';
$isFromDoc ? null : dropmenu();
if($isFromDoc)
{
jsVar('blockID', $blockID);
$this->app->loadLang('doc');
$productChangeLink = createLink('release', 'browse', "productID={productID}&branch=$branch&type=$type&orderBy=$orderBy&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}&from=$from&blockID=$blockID");
jsVar('insertListLink', createLink('release', 'browse', "productID={$product->id}&branch=$branch&type=$type&orderBy=$orderBy&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}&from=$from&blockID={blockID}"));
formPanel
(
setID('zentaolist'),
setClass('mb-4-important'),
set::title(sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList['productRelease'])),
set::actions(array()),
set::showExtra(false),
to::titleSuffix
(
span
(
setClass('text-muted text-sm text-gray-600 font-light'),
span
(
setClass('text-warning mr-1'),
icon('help'),
),
$lang->doc->previewTip
)
),
formRow
(
formGroup
(
set::width('1/2'),
set::name('product'),
set::label($lang->doc->product),
set::control(array('required' => false)),
set::items($products),
set::value($product->id),
set::required(),
span
(
setClass('error-tip text-danger hidden'),
$lang->doc->emptyError
),
on::change('[name="product"]')->do("loadModal('$productChangeLink'.replace('{productID}', $(this).val()))")
)
)
);
}
/* zin: Define the set::module('release') feature bar on main menu. */
featureBar
(
set::current($type),
set::linkParams("productID={$product->id}&branch={$branch}&type={key}&orderBy={$orderBy}&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"),
li(searchToggle(set::module('release'), set::open($type == 'bySearch')))
set::linkParams("productID={$product->id}&branch={$branch}&type={key}&orderBy={$orderBy}&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}&from={$from}&blockID={$blockID}"),
set::isModal($isFromDoc),
set::modalTarget('#releases_table'),
li(searchToggle
(
set::simple($isFromDoc),
set::open($type == 'bysearch'),
set::module('release'),
$isFromDoc ? set::target('#docSearchForm') : null
))
);
if($isFromDoc) div(setID('docSearchForm'));
/* zin: Define the toolbar on main menu. */
$canCreateRelease = hasPriv('release', 'create') && common::canModify('product', $product);
$canManageSystem = hasPriv('system', 'browse') && common::canModify('product', $product);
@@ -27,6 +90,7 @@ if($canCreateRelease) $createItem = array('icon' => 'plus', 'class' => 'primary'
if($canManageSystem) $manageSystemItem = array('class' => 'primary', 'text' => $lang->release->manageSystem, 'url' => $this->createLink('system', 'browse', "productID={$product->id}"), 'data-app' => 'product');
toolbar
(
setClass(array('hidden' => $isFromDoc)),
!empty($manageSystemItem) ? item(set($manageSystemItem)) : null,
!empty($createItem) ? item(set($createItem)) : null
);
@@ -44,19 +108,31 @@ foreach(array_column($releases, 'system') as $system)
}
if(!empty($cols['system'])) $cols['system']['map'] = array(0 => '') + $appList;
if($isFromDoc)
{
$cols['id']['type'] = 'checkID';
if(isset($cols['actions'])) unset($cols['actions']);
foreach($cols as $key => $col)
{
$cols[$key]['sortType'] = false;
if(isset($col['link'])) unset($cols[$key]['link']);
}
}
$releases = initTableData($releases, $cols, $this->release);
dtable
(
set::id('releases'),
set::cols(array_values($cols)),
set::data($releases),
set::customCols(true),
set::rowKey('rowID'),
set::plugins(array('cellspan')),
set::onRenderCell(jsRaw('window.renderCell')),
set::getCellSpan(jsRaw('window.getCellSpan')),
set::orderBy($orderBy),
set::sortLink(createLink('release', 'browse', "productID={$product->id}&branch={$branch}&type={$type}&orderBy={name}_{sortType}&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}")),
set::footer([jsRaw("function(){return {html: '{$pageSummary}'};}"), 'flex', 'pager']),
set::footPager(
usePager
(
@@ -64,8 +140,14 @@ dtable
)
),
set::emptyTip($lang->release->noRelease),
set::createTip($lang->release->create),
set::createLink($canCreateRelease ? createLink('release', 'create', "productID={$product->id}&branch={$branch}") : '')
set::checkable($isFromDoc),
$isFromDoc ? set::footToolbar(array(array('text' => $lang->doc->insertText, 'data-on' => 'click', 'data-call' => 'insertListToDoc'))) : set::footer([jsRaw("function(){return {html: '{$pageSummary}'};}"), 'flex', 'pager']),
!$isFromDoc ? null : set::afterRender(jsCallback()->call('toggleCheckRows', $idList)),
!$isFromDoc ? null : set::height(400),
$isFromDoc ? null : set::customCols(true),
$isFromDoc ? null : set::sortLink(createLink('release', 'browse', "productID={$product->id}&branch={$branch}&type={$type}&orderBy={name}_{sortType}&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}")),
$isFromDoc ? null : set::createTip($lang->release->create),
$isFromDoc ? null : set::createLink($canCreateRelease ? createLink('release', 'create', "productID={$product->id}&branch={$branch}") : '')
);
/* ====== Render page ====== */