* task #8711, add tabs menu for mdule groups.

This commit is contained in:
Catouse
2020-12-28 08:29:58 +08:00
parent 6b0d4b50ff
commit 5c7acd9d9a
12 changed files with 422 additions and 36 deletions
+3 -3
View File
@@ -559,9 +559,9 @@ class caselib extends control
/**
* Show import case.
*
* @param int $libID
* @param int $pagerID
* @param int $maxImport
* @param int $libID
* @param int $pagerID
* @param int $maxImport
* @param string|int $insert 0 is covered old, 1 is insert new.
* @access public
* @return void
+49 -9
View File
@@ -527,26 +527,66 @@ class commonModel extends model
* Print the main nav.
*
* @param string $moduleName
* @param string $methodName
*
* @static
* @access public
* @return void
*/
public static function printMainNav($moduleName, $methodName = '')
public static function printMainNav($moduleName)
{
global $app, $lang;
$items = common::getMainNavList($moduleName);
foreach($items as $item)
{
if($item == 'divider')
{
echo "<li class='divider'></li>";
}
else
{
$active = $item->active ? ' class="active"' : '';
echo "<li$active>" . html::a($item->url, $item->title) . '</li>';
}
}
}
$lastMenu = end($lang->mainNav);
/**
* Get main nav items list
*
* @param string $moduleName
*
* @static
* @access public
* @return array
*/
public static function getMainNavList($moduleName)
{
global $lang;
$items = array();
$lastNavItem = end($lang->mainNav);
foreach($lang->mainNav as $group => $nav)
{
$active = '';
list($title, $currentModule, $currentMethod, $vars) = explode('|', $nav);
if($moduleName != 'program' && $moduleName == $group) $active = 'active';
if(zget($lang->navGroup, $moduleName, '') == $group) $active = 'active';
if(common::hasPriv($currentModule, $currentMethod)) echo "<li class=$active>" . html::a(helper::createLink($currentModule, $currentMethod, $vars), $title) . '</li>';
if(($lastMenu != $nav) && strpos($lang->dividerMenu, ",{$group},") !== false) echo "<li class='divider'></li>";
if(!common::hasPriv($currentModule, $currentMethod)) continue;
$item = new stdClass();
$item->group = $group;
$item->active = zget($lang->navGroup, $moduleName, '') == $group || $moduleName != 'program' && $moduleName == $group;
$item->title = $title;
$item->moduleName = $currentModule;
$item->methodName = $currentMethod;
$item->vars = $vars;
$item->url = helper::createLink($currentModule, $currentMethod, $vars);
$items[] = $item;
if(($lastNavItem != $nav) && strpos($lang->dividerMenu, ",{$group},") !== false)
{
$items[] = 'divider';
}
}
return $items;
}
/**
-14
View File
@@ -10,20 +10,6 @@ include 'chosen.html.php';
<?php $isProgram = (zget($lang->navGroup, $app->rawModule) == 'program');?>
<?php $isProduct = (zget($lang->navGroup, $app->rawModule) == 'product');?>
<?php $isProject = (zget($lang->navGroup, $app->rawModule) == 'project');?>
<div id='menu'>
<nav id='menuNav'>
<ul class='nav nav-default'>
<?php commonModel::printMainNav($app->rawModule);?>
<?php commonModel::getRecentExecutions();?>
</ul>
</nav>
<div id='menuFooter'>
<button type='button' id='menuToggle'><i class='icon icon-sm icon-menu-collapse'></i></button>
</div>
<div class="table-col col-right" id="moreExecution">
<div class="list-group" id="executionList"></div>
</div>
</div>
<header id='header'>
<div id='mainHeader'>
<div class='container'>
+1 -1
View File
@@ -70,7 +70,7 @@ $extHookFiles = glob($extHookRule);
if($extHookFiles) foreach($extHookFiles as $extHookFile) include $extHookFile;
?>
</head>
<?php if($this->cookie->hideMenu): ?>
<?php if($this->moduleName == 'index' && $this->methodName == 'index' && $this->cookie->hideMenu): ?>
<body class='menu-hide'>
<?php else: ?>
<body>
+8 -5
View File
@@ -15,7 +15,7 @@ class index extends control
{
/**
* Construct function, load project, product.
*
*
* @access public
* @return void
*/
@@ -26,18 +26,21 @@ class index extends control
/**
* The index page of whole zentao system.
*
*
* @access public
* @return void
*/
public function index()
public function index($open = '')
{
$this->locate($this->createLink('my', 'index'));
$this->view->open = helper::safe64Decode($open);
$this->view->title = $this->lang->index->common;
$this->display();
}
/**
* Just test the extension engine.
*
*
* @access public
* @return void
*/
+13
View File
@@ -0,0 +1,13 @@
#pages {position: fixed; left: 96px; bottom: 0; right: 0; top: 0;}
.page-tab {position: absolute; left: 0; bottom: 0; right: 0; top: 0; background-color: #efefef;}
.menu-hide #pages {left: 0}
#pagesBar {position: fixed; left: 96px; bottom: 0; right: 0; height: 40px; z-index: 1012; background: #fff; border-top: 1px solid #eff1f7;}
#bars {position: absolute; left: 0; top: 0; bottom: 0; padding: 0 5px}
#bars > li {padding: 8px 5px;}
#bars > li > a {height: 24px; color: #fff; background: #cccfd4; padding: 2px 8px; line-height: 20px; border-radius: 2px;}
#bars > li > a:hover, #bars > li > a:active, #bars > li > a:focus {background: #3c495c}
#bars > li.active > a, #bars > li.active > a:active, #bars > li.active > a:focus {background: #0c64eb}
#bars > li.active:after {content: ' '; display: block; position: absolute; background: #a0cafa; height: 3px; left: 5px; right: 5px; bottom: 0; border-radius: 2px;}
.menu-hide #pagesBar {left: 40px}
+280
View File
@@ -0,0 +1,280 @@
(function()
{
/* Init variables */
var openedTabs = {}; // Key-value to save group-tab pairs
var groupsMap = {}; // Key-value to save group-menu pairs
var openedTabZIndex = 10; // Last opened tab z-index
var defaultTabGroup; // Default tab group
var lastOpenedGroup; // Last opened tab group
/**
* Init menu list
*/
function initMenuList()
{
var $menuMainNav = $('#menuMainNav').empty();
window.menuItems.forEach(function(item)
{
if(item === 'divider') return $menuMainNav.append('<li class="divider"></li>');
var $link= $('<a></a>').attr('href', item.url)
.attr('data-group', item.group)
.attr('class', 'show-in-tab')
.html(item.title);
$('<li></li>').attr('data-group', item.group)
.append($link)
.appendTo($menuMainNav);
item.icon = $link.find('.icon').attr('class').replace('icon ', '');
item.text = $link.text().trim();
groupsMap[item.group] = item;
if(!defaultTabGroup) defaultTabGroup = item.group;
});
}
/**
* Open tab
* @param {string} [url] Url to open in tab
* @param {string} [group] The group of target tab to open
* @return {void}
*/
function openTab(url, group)
{
/* Check params */
if(!group)
{
if(groupsMap[url])
{
group = url;
url = '';
}
else
{
var moduleName = $.parseLink(url).moduleName;
group = window.navGroup[moduleName] || moduleName;
}
}
/* Highlight at main menu */
var $menuMainNav = $('#menuMainNav');
var $lastActiveNav = $menuMainNav.find('li.active');
if($lastActiveNav.data('group') !== group)
{
$lastActiveNav.removeClass('active');
$menuMainNav.find('li[data-group="' + group + '"]').addClass('active');
}
/* Create pate tab object and store it */
var tab = openedTabs[group];
if(!tab)
{
var $iframe = $(
[
'<iframe',
'id="tabIframe-' + group + '"',
'name="tab-' + group + '"',
'frameborder="no"',
'allowtransparency="true"',
'scrolling="auto"',
'style="width: 100%; height: 100%; left: 0px;"',
'/>'
].join(' '));
var $page = $('<div class="page-tab" id="tab-' + group + '"></div>')
.append($iframe)
.appendTo('#pages');
tab = $.extend({$iframe: $iframe, $page: $page, group: group}, groupsMap[group]);
openedTabs[group] = tab;
/* If first show without url, then use the default url */
if(!url) url = groupsMap[group].url;
}
/* Show page tab and update iframe source */
if(url) reloadTab(group, url);
tab.zIndex = openedTabZIndex++;
tab.$page.show().css('z-index', tab.zIndex);
/* Update task bar */
var $bars = $('#bars');
var $bar = $('#tabBar-' + group);
if(!$bar.length)
{
var $link= $('<a></a>').attr('href', tab.url)
.attr('data-group', group)
.attr('class', 'show-in-tab')
.html(tab.text);
$bar = $('<li></li>').attr('data-group', group)
.attr('id', 'tabBar-' + group)
.append($link)
.appendTo($bars);
}
var $lastActiveBar = $bars.find('li.active');
if($lastActiveBar.data('group') !== group)
{
$lastActiveBar.removeClass('active');
$bars.find('li[data-group="' + group + '"]').addClass('active');
}
tab.$bar = $bar;
/* Update tab state */
tab.show = true;
lastOpenedGroup = group;
}
/**
* Get last opened tab
* @param {boolean} [onlyShowed] If set to true then only get last tab from tabs are showed
* @returns {object} The opened tab info object
*/
function getLastTab(onlyShowed)
{
var lastShowIndex = 0;
var lastTab = null;
for(var group in openedTabs)
{
var tab = openedTabs[group];
if((!onlyShowed || tab.show) && lastShowIndex < tab.zIndex)
{
lastShowIndex = tab.zIndex;
lastTab = tab;
}
}
return lastTab;
}
/**
* Hide tab
* @param {string} group The group of target tab to hide
* @return {void}
*/
function hideTab(group)
{
var tab = openedTabs[group];
if(!tab || !tab.show) return;
tab.$page.hide();
tab.show = false;
lastOpenedGroup = null;
/* Active last tab */
var lastTab = getLastTab(true) || getLastTab();
showTab(lastTab ? lastTab.group : defaultTabGroup);
}
/**
* Show tab
* @param {string} group The group of target tab to show
* @return {void}
*/
function showTab(group)
{
return openTab('', group);
}
/**
* Toggle tab
* @param {string} group The group of target tab to toggle
* @return {void}
*/
function toggleTab(group)
{
var tab = openedTabs[group];
if(!tab || tab.group !== lastOpenedGroup) showTab(group);
else hideTab(group);
}
/**
* Close tab
* @param {string} group The group of target tab to close
*/
function closeTab(group)
{
var tab = openedTabs[group];
if(!tab) return;
hideTab(group);
tab.$page.remove();
tab.$bar.remove();
delete openedTabs[group];
}
/**
* Reload tab
* @param {string} group The group of target tab to reload
* @param {string|boolean} [url] The new url to load, it's optional
* @return {void}
*/
function reloadTab(group, url)
{
var tab = openedTabs[group];
if(!tab) return;
if(url === true) url = tab.url;
var iframe = tab.$iframe[0];
try
{
if(url) iframe.contentWindow.location.assign(url);
else iframe.contentWindow.location.reload(true);
}
catch(_)
{
iframe.src = url || iframe.contentWindow.location.href;
}
}
/* Bind helper methods to global object "$.tabs" */
$.tabs = window.tabs =
{
show: showTab,
open: openTab,
hide: hideTab,
toggle: toggleTab,
close: closeTab,
reload: reloadTab,
openedTabs: openedTabs,
groupsMap: groupsMap
};
/* Init after current page load */
$(function()
{
initMenuList();
/* Bind events */
$(document).on('click', '.open-in-tab,.show-in-tab', function(e)
{
var $link = $(this);
var url = $link.hasClass('open-in-tab') ? ($link.attr('href') || $link.data('url')) : '';
openTab(url, $link.data('group'));
e.preventDefault();
}).on('contextmenu', '.open-in-tab,.show-in-tab', function(event)
{
var group = $(this).data('group');
if(!group) return;
var lang = window.tabsLang;
var tab = openedTabs[group];
var items = [{label: lang.open, onClick: function(){showTab(group)}}];
if(tab)
{
items.push({label: lang.reload, onClick: function(){reloadTab(group)}});
items.push({label: lang.close, onClick: function(){closeTab(group)}});
}
$.zui.ContextMenu.show(items, {event: event});
event.preventDefault();
});
/* Redirect or open default tab after document load */
var defaultOpenUrl = window.defaultOpen;
if(!defaultOpenUrl)
{
defaultOpenUrl = $.cookie('open-in-tab');
if(defaultOpenUrl) $.cookie('open-in-tab', null);
}
if(defaultOpenUrl) openTab(defaultOpenUrl);
else openTab(defaultTabGroup);
});
}());
+5
View File
@@ -1,3 +1,8 @@
<?php
$lang->index->common = 'Home';
$lang->index->index = 'Home';
$lang->index->tab = new stdClass();
$lang->index->tab->open = 'Open';
$lang->index->tab->reload = 'Reload';
$lang->index->tab->close = 'Close';
+5
View File
@@ -1,3 +1,8 @@
<?php
$lang->index->common = '首页';
$lang->index->index = '首页';
$lang->index->tab = new stdClass();
$lang->index->tab->open = '打开';
$lang->index->tab->reload = '刷新';
$lang->index->tab->close = '关闭';
+54
View File
@@ -0,0 +1,54 @@
<?php
/**
* The html template file of index method of index module of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Hao Sun <sunhao@cnezsoft.com>
* @package ZenTaoPMS
* @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $
*/
?>
<?php
include '../../common/view/header.lite.html.php';
$this->app->loadConfig('sso');
if(!empty($config->sso->redirect)) js::set('ssoRedirect', $config->sso->redirect);
$isProduct = (zget($lang->navGroup, $app->rawModule) == 'product');
$isProgram = (zget($lang->navGroup, $app->rawModule) == 'program');
$isProject = (zget($lang->navGroup, $app->rawModule) == 'project');
js::set('navGroup', $lang->navGroup);
js::set('tabsLang', $lang->index->tab);
js::set('menuItems', commonModel::getMainNavList($app->rawModule));
js::set('defaultOpen', $open);
?>
<div id='menu'>
<nav id='menuNav' data-group='<?php echo $app->rawModule; ?>'>
<ul class='nav nav-default' id='menuMainNav'>
</ul>
<ul class='nav nav-default'>
<?php commonModel::getRecentExecutions();?>
</ul>
</nav>
<div id='menuFooter'>
<button type='button' id='menuToggle'><i class='icon icon-sm icon-menu-collapse'></i></button>
</div>
<div class="table-col col-right" id="moreExecution">
<div class="list-group" id="executionList"></div>
</div>
</div>
<div id='pages'>
</div>
<div id='pagesBar'>
<ul id='bars' class='nav nav-default'></ul>
<div id='poweredBy'>
<small class='muted'><?php echo $lang->designedByAIUX;?></small> &nbsp;
<a href='<?php echo $lang->website;?>' target='_blank'><i class='icon-zentao'></i> <?php echo $lang->zentaoPMS . $config->version;?></a> &nbsp;
<?php echo $lang->proVersion;?>
<?php if(isset($config->xxserver->installed) and $config->xuanxuan->turnon) commonModel::printClientLink();?>
</div>
</div>
<?php include '../../common/view/footer.lite.html.php';?>
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long