* task #8711, add tabs menu for mdule groups.
This commit is contained in:
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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'>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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}
|
||||
@@ -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);
|
||||
});
|
||||
}());
|
||||
@@ -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';
|
||||
|
||||
@@ -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 = '关闭';
|
||||
|
||||
@@ -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>
|
||||
<a href='<?php echo $lang->website;?>' target='_blank'><i class='icon-zentao'></i> <?php echo $lang->zentaoPMS . $config->version;?></a>
|
||||
<?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
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