* add menu custom UI.

This commit is contained in:
Catouse
2016-04-21 08:45:43 +08:00
parent 0d727fc3d8
commit 27676eeb4b
10 changed files with 275 additions and 30 deletions
+7 -7
View File
@@ -176,7 +176,7 @@ $lang->todo->menu = $lang->my->menu;
$lang->product = new stdclass();
$lang->product->menu = new stdclass();
$lang->product->menu->list = '%s';
$lang->product->menu->list = array('link' => '%s' . $lang->arrow, 'fixed' => true);
$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->dynamic = 'Dynamic|product|dynamic|productID=%s';
$lang->product->menu->plan = array('link' => 'Plan|productplan|browse|productID=%s', 'subModule' => 'productplan');
@@ -204,7 +204,7 @@ $lang->release->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->list = '%s';
$lang->project->menu->list = array('link' => '%s', 'fixed' => true);
$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,importbug,burn');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
@@ -227,7 +227,7 @@ $lang->build->menu = $lang->project->menu;
$lang->qa = new stdclass();
$lang->qa->menu = new stdclass();
$lang->qa->menu->product = '%s';
$lang->qa->menu->product = array('link' => '%s', 'fixed' => true);
$lang->qa->menu->index = '首页|qa|index|locate=no&productID=%s';
$lang->qa->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
$lang->qa->menu->testcase = array('link' => 'Case|testcase|browse|productID=%s');
@@ -236,7 +236,7 @@ $lang->qa->menu->testtask = array('link' => 'Build|testtask|browse|productID=%s'
$lang->bug = new stdclass();
$lang->bug->menu = new stdclass();
$lang->bug->menu->product = '%s';
$lang->bug->menu->product = array('link' => '%s', 'fixed' => true);
$lang->bug->menu->index = 'Index|qa|index|locate=no&productID=%s';
$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
$lang->bug->menu->testcase = array('link' => 'Case|testcase|browse|productID=%s');
@@ -245,7 +245,7 @@ $lang->bug->menu->testtask = array('link' => 'Build|testtask|browse|productID=%s
$lang->testcase = new stdclass();
$lang->testcase->menu = new stdclass();
$lang->testcase->menu->product = '%s';
$lang->testcase->menu->product = array('link' => '%s', 'fixed' => true);
$lang->testcase->menu->index = 'Index|qa|index|locate=no&productID=%s';
$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
$lang->testcase->menu->testcase = array('link' => 'Case|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit,showimport,groupcase', 'subModule' => 'tree');
@@ -258,7 +258,7 @@ $lang->testtask->menu = $lang->testcase->menu;
$lang->doc = new stdclass();
$lang->doc->menu = new stdclass();
$lang->doc->menu->list = '%s';
$lang->doc->menu->list = array('link' => '%s', 'fixed' => true);
$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s', 'alias' => 'view,create,edit');
$lang->doc->menu->edit = 'Edit Library|doc|editLib|libID=%s';
$lang->doc->menu->module = 'Modules|tree|browse|libID=%s&viewType=doc';
@@ -277,7 +277,7 @@ $lang->report->menu->staff = array('link' => 'Company|report|workload');
/* Company menu. */
$lang->company = new stdclass();
$lang->company->menu = new stdclass();
$lang->company->menu->name = '%s' . $lang->arrow;
$lang->company->menu->name = array('link' => '%s' . $lang->arrow, 'fixed' => true);
$lang->company->menu->browseUser = array('link' => 'Users|company|browse', 'subModule' => 'user');
$lang->company->menu->dept = array('link' => 'Department|dept|browse', 'subModule' => 'dept');
$lang->company->menu->browseGroup = array('link' => 'Group|group|browse', 'subModule' => 'group');
+6 -6
View File
@@ -205,7 +205,7 @@ $lang->release->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->list = '%s';
$lang->project->menu->list = array('link' => '%s', 'fixed' => true);
$lang->project->menu->index = '首页|project|index|locate=no';
$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree');
$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
@@ -229,7 +229,7 @@ $lang->build->menu = $lang->project->menu;
$lang->qa = new stdclass();
$lang->qa->menu = new stdclass();
$lang->qa->menu->product = '%s';
$lang->qa->menu->product = array('link' => '%s', 'fixed' => true);
$lang->qa->menu->index = '首页|qa|index|locate=no&productID=%s';
$lang->qa->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
$lang->qa->menu->testcase = array('link' => '用例|testcase|browse|productID=%s');
@@ -238,7 +238,7 @@ $lang->qa->menu->testtask = array('link' => '版本|testtask|browse|productID=%s
$lang->bug = new stdclass();
$lang->bug->menu = new stdclass();
$lang->bug->menu->product = '%s';
$lang->bug->menu->product = array('link' => '%s', 'fixed' => true);
$lang->bug->menu->index = '首页|qa|index|locate=no&productID=%s';
$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
$lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=%s');
@@ -247,7 +247,7 @@ $lang->bug->menu->testtask = array('link' => '版本|testtask|browse|productID=%
$lang->testcase = new stdclass();
$lang->testcase->menu = new stdclass();
$lang->testcase->menu->product = '%s';
$lang->testcase->menu->product = array('link' => '%s', 'fixed' => true);
$lang->testcase->menu->index = '首页|qa|index|locate=no&productID=%s';
$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit,showimport,groupcase', 'subModule' => 'tree');
@@ -260,7 +260,7 @@ $lang->testtask->menu = $lang->testcase->menu;
$lang->doc = new stdclass();
$lang->doc->menu = new stdclass();
$lang->doc->menu->list = '%s';
$lang->doc->menu->list = array('link' => '%s', 'fixed' => true);
$lang->doc->menu->browse = array('link' => '文档|doc|browse|libID=%s', 'alias' => 'view,create,edit');
$lang->doc->menu->edit = '编辑|doc|editLib|libID=%s';
$lang->doc->menu->module = '分类|tree|browse|libID=%s&viewType=doc';
@@ -279,7 +279,7 @@ $lang->report->menu->staff = array('link' => '组织|report|workload');
/* 组织结构视图菜单设置。*/
$lang->company = new stdclass();
$lang->company->menu = new stdclass();
$lang->company->menu->name = '%s' . $lang->arrow;
$lang->company->menu->name = array('link' => '%s' . $lang->arrow, 'fixed' => true);
$lang->company->menu->browseUser = array('link' => '用户|company|browse', 'subModule' => 'user');
$lang->company->menu->dept = array('link' => '部门|dept|browse', 'subModule' => 'dept');
$lang->company->menu->browseGroup = array('link' => '权限|group|browse', 'subModule' => 'group');
+3 -4
View File
@@ -406,8 +406,8 @@ class commonModel extends model
$link = is_array($menuItem->link) ? helper::createLink($menuItem->link['module'], $menuItem->link['method'], $menuItem->link['vars']) : $menuItem->link;
echo "<li $active data-id='$menuItem->name'><a href='$link' $active>$menuItem->text</a></li>\n";
}
$customLink = helper::createLink('custom', 'menu');
echo "<li class='custom-item'><a href='$customLink' data-toggle='modal' data-type='iframe' title='$lang->customMenu' data-icon='cog'><i class='icon icon-cog'></i></a></li>";
$customLink = helper::createLink('custom', 'menu', "module={$app->getModuleName()}&method={$app->getMethodName()}", '', true);
echo "<li class='custom-item'><a href='$customLink' data-toggle='modal' data-type='iframe' title='$lang->customMenu' data-icon='cog' data-width='80%'><i class='icon icon-cog'></i></a></li>";
echo "</ul>\n";
}
@@ -488,7 +488,7 @@ class commonModel extends model
if($menuItem->link)
{
$active = '';
$float = '';
$float = $menuItem->float;
$alias = '';
$target = '';
$module = '';
@@ -503,7 +503,6 @@ class commonModel extends model
}
$alias = $menuItem->link['alias'];
$target = $menuItem->link['target'];
$float = $menuItem->link['float'];
$module = $menuItem->link['module'];
$method = $menuItem->link['method'];
}
+24 -6
View File
@@ -188,25 +188,43 @@ class custom extends control
* @access public
* @return void
*/
public function menu($module = 'main', $method = '')
public function menu($module = 'main', $method = '', $type = '')
{
global $config;
if($_POST)
{
$account = $this->app->user->account;
$menu = $_POST['menu'];
if(empty($method))
{
$config->menucustom->$module = $_POST['menu'];
$this->loadModel('setting')->setItem("$account.menucustom.$module", $menu);
}
else
{
$configKey = 'menucustom' . $module;
$config->$configKey->$method = $_POST['menu'];
$this->loadModel('setting')->setItem("$account.$configKey.$method", $menu);
}
$this->send(array('result' => 'success', 'menu' => $_POST['menu']));
$this->send(array('result' => 'success', 'menu' => $menu));
}
if($this->viewType === 'json')
{
$menu = !empty($method) ? customModel::getFeatureMenu($module, $method) : customModel::getModuleMenu($module);
if($type === 'all')
{
$menu = array();
$menu['main'] = customModel::getModuleMenu('main', true);
if($module !== 'main')
{
$menu['module'] = customModel::getModuleMenu($module, true);
$menu['feature'] = customModel::getFeatureMenu($module, $method);
$menu['moduleName'] = $module;
$menu['methodName'] = $method;
}
}
else
{
$menu = !empty($method) ? customModel::getFeatureMenu($module, $method) : customModel::getModuleMenu($module, true);
}
$this->send(array('result' => $menu ? 'success' : 'fail', 'menu' => $menu));
}
else
+19
View File
@@ -0,0 +1,19 @@
#loadingIcon {opacity: 0; transition: opacity .3s}
#loadingIcon.active {opacity: 1}
#menuEditor {padding: 20px;}
#menuEditor > .panel {background-color: #003366; border: none; padding-top: 10px;}
#modulemenu, #featurebar {margin: 0; border-left: 1px solid #ddd; border-right: 1px solid #ddd; padding-left: 10px; padding-right: 10px;}
#mainmenu {padding-left: 10px; padding-right: 10px;}
#featurebar {border-top: 1px solid #ddd}
#featurebar > .nav {width: 100%}
#menuEditor .nav > li > a .item-hidden-icon {display: none}
#menuEditor .nav > li.menu-hidden > a .item-hidden-icon {display: inline-block; margin-left: 5px;}
#menuEditor .nav > li.menu-hidden {opacity: 0.5;}
#menuEditor.preview .nav > li.menu-hidden {display: none}
#menuEditor .nav > li.menu-hidden > a {position: relative;}
#menuEditor .nav > li.menu-hidden > a:before {content: ' '; display: block; position: absolute; top: 0; bottom: 0; right: 0; left: 0; background-color: rgba(0,0,0,.1); border: 1px dashed #aaa}
#modulemenu .nav > li.menu-hidden {margin-left: 3px;}
#titlebar > .heading > i,
#titlebar > .heading > strong > i {display: inline-block;}
+129
View File
@@ -0,0 +1,129 @@
$(function()
{
var currentModule = startMenu['module'],
currentMethod = startMenu['method'];
var $mainMenu = $('#mainmenu'),
$moduleMenu = $('#modulemenu'),
$featureMenu = $('#featurebar'),
$loadingIcon = $('#loadingIcon'),
$menuEditor = $('#menuEditor');
var menuConfig = {
'main': null,
'module': {},
'feature': {}
};
var updateMenu = function($menu, items)
{
if(items)
{
var $nav = $('<ul class="nav"/>');
$.each(items, function(idx, item)
{
if(!item.text || item.fixed) return;
var $a = $('<a href="#"/>').html(item.text).data('menu', item).append('<i class="item-hidden-icon icon icon-eye-close"></i>');
$('<li/>').attr('data-id', item.name).toggleClass('right', item.float === 'right').toggleClass('menu-hidden', !!item.hidden).append($a).appendTo($nav);
});
$nav.sortable();
$menu.children('ul').replaceWith($nav);
}
else
{
$menu.children('ul').empty();
}
};
var activeCurrent = function(moduleName, methodName)
{
currentModule = moduleName;
currentMethod = methodName;
$mainMenu.find('li.active').removeClass('active');
$mainMenu.find('li[data-id="' + moduleName + '"]').addClass('active');
$moduleMenu.find('li.active').removeClass('active');
$moduleMenu.find('li[data-id="' + methodName + '"]').addClass('active');
};
var loadData = function(moduleName, methodName, type)
{
type = type || '';
var link = createLink('custom', 'menu', 'module=' + moduleName + '&method=' + methodName + '&type=' + type, 'json');
$loadingIcon.addClass('active');
$.get(link, function(data)
{
console.log(data);
if(data.result === 'success' && data.menu)
{
var menu = data.menu;
if(menu['main'])
{
updateMenu($mainMenu, menu['main']);
menuConfig['main'] = menu['main'];
}
if(menu['module'])
{
updateMenu($moduleMenu, menu['module']);
menuConfig['module'][moduleName] = menu['module'];
}
if(menu['feature'] !== undefined)
{
updateMenu($featureMenu, menu['feature']);
if(!menuConfig['feature'][moduleName]) menuConfig['feature'][moduleName] = {};
menuConfig['feature'][moduleName][methodName] = menu['feature'];
}
}
activeCurrent(moduleName, methodName);
$loadingIcon.removeClass('active');
}, 'json');
};
$menuEditor.on('mouseenter', '.nav > li > a', function()
{
// var $a = $(this);
// var item = $a.data('menu');
// var $menu = $a.closest('nav');
// var moduleName = item.link && item.link['module'] ? item.link['module'] : item.name;
// var methodName = item.link && item.link['method'] ? item.link['method'] : '';
// if($menu.is('#modulemenu'))
// {
// moduleName = currentModule;
// methodName = item.name;
// }
// if(moduleName !== currentModule || methodName !== currentMethod)
// {
// if($menu.is('#mainmenu,#modulemenu'))
// {
// if(menuConfig['module'][moduleName] !== undefined && menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined)
// {
// updateMenu($moduleMenu, menuConfig['module'][moduleName]);
// updateMenu($featureMenu, menuConfig['feature'][moduleName][methodName]);
// activeCurrent(moduleName, methodName);
// }
// else
// {
// loadData(moduleName, methodName, 'all');
// }
// }
// }
}).on('click', '.nav > li > a', function()
{
var $a = $(this);
var item = $a.data('menu');
var $menu = $a.closest('nav');
var moduleName = item.link && item.link['module'] ? item.link['module'] : item.name;
var methodName = item.link && item.link['method'] ? item.link['method'] : '';
if($menu.is('#modulemenu'))
{
moduleName = currentModule;
methodName = item.name;
}
$a.parent().toggleClass('menu-hidden');
});
$('#saveMenuBtn').click(function()
{
console.log('save', menuConfig);
}).on('mouseenter', function() {$menuEditor.addClass('preview')})
.on('mouseout', function() {$menuEditor.removeClass('preview')});
loadData(currentModule, currentMethod, 'all');
});
+2
View File
@@ -79,3 +79,5 @@ $lang->custom->productproject->relation['0_1'] = 'Product - Sprint';
$lang->custom->productproject->relation['1_1'] = 'Project - Sprint';
$lang->custom->productproject->notice = 'You can change the name of product and project, and the corresponding name display';
$lang->custom->menuTip = 'Click menu item to toggle display status, drag and drop to change display order.';
+2
View File
@@ -79,3 +79,5 @@ $lang->custom->productproject->relation['0_1'] = '产品 - 迭代';
$lang->custom->productproject->relation['1_1'] = '项目 - 迭代';
$lang->custom->productproject->notice = '请根据实际情况选择适合自己团队的概念。';
$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。';
+41 -7
View File
@@ -132,20 +132,38 @@ class customModel extends model
*/
public static function buildMenuConfig($allMenu, $menuConfig)
{
global $app, $lang, $config;
$isSetMenuConfig = isset($menuConfig);
$menu = array();
$order = 1;
$menuConfigMap = array();
if($isSetMenuConfig)
{
if(is_string($menuConfig))
{
$menuConfigItems = explode(',', $menuConfig);
$menuConfig = array();
foreach($menuConfigItems as $menuConfigItem)
{
$menuConfig[$menuConfigItem] = true;
$item = new stdclass();
$item->name = $menuConfigItem;
$item->order = $order++;
$item->hidden = false;
$menuConfigMap[$item->name] = $item;
}
}
else if(is_array($menuConfig))
{
foreach($menuConfig as $menuConfigItem)
{
if(!isset($menuConfigItem->order)) $menuConfigItem->order = $order++;
$menuConfigMap[$menuConfigItem->name] = $menuConfigItem;
}
}
else
{
$isSetMenuConfig = false;
}
}
foreach($allMenu as $name => $item)
@@ -153,6 +171,10 @@ class customModel extends model
$label = '';
$module = '';
$method = '';
$float = '';
$fixed = '';
$hidden = $isSetMenuConfig && $menuConfigMap[$name] && $menuConfigMap[$name]->hidden;
$link = is_array($item) ? $item['link'] : $item;
if(strpos($link, '|') !== false)
{
@@ -176,21 +198,31 @@ class customModel extends model
$itemLink['subModule'] = $item['subModule'];
$itemLink['alias'] = $item['alias'];
$itemLink['target'] = $item['target'];
$itemLink['float'] = $item['float'];
}
}
if(is_array($item))
{
$float = $item['float'];
$fixed = $item['fixed'];
}
$menuItem = new stdclass();
$menuItem->name = $name;
$menuItem->link = $itemLink;
$menuItem->text = $label;
$menuItem->source = $item;
$menuItem->hidden = $isSetMenuConfig && (!$menuConfig[$name]);
$menu[] = $menuItem;
$menuItem->order = $isSetMenuConfig && $menuConfigMap[$name] && isset($menuConfigMap[$name]->order) ? $menuConfigMap[$name]->order : $order++;
if($float) $menuItem->float = $float;
if($fixed) $menuItem->fixed = $fixed;
if($hidden) $menuItem->hidden = $hidden;
$menu[$menuItem->order] = $menuItem;
}
}
return $menu;
ksort($menu, SORT_NUMERIC);
return array_values($menu);
}
/**
@@ -209,6 +241,7 @@ class customModel extends model
if(!$rebuild && !empty($app->customMenu[$module])) return $app->customMenu[$module];
$menuConfig = $config->menucustom->$module;
if(!empty($menuConfig)) $menuConfig = json_decode($menuConfig);
if(!isset($menuConfig) && common::inNoviceMode()) $menuConfig = $config->menu->$module['novice'];
$allMenu = $module == 'main' ? $lang->menu : $lang->$module->menu;
@@ -243,6 +276,7 @@ class customModel extends model
$configKey = 'menucustom' . $module;
$menuConfig = $config->$configKey->$method;
if(!empty($menuConfig)) $menuConfig = json_decode($menuConfig);
$allMenu = $lang->$module->featurebar[$method];
return $allMenu ? self::buildMenuConfig($allMenu, $menuConfig) : null;
+42
View File
@@ -0,0 +1,42 @@
<?php
/**
* The menu view of custom module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(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 user
* @version $Id: edit.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div class='container mw-800px'>
<div id='titlebar'>
<div class='heading'>
<i class='icon icon-cog'></i> <strong><?php echo $lang->customMenu ?></strong> <i class='icon icon-spin icon-spinner' id='loadingIcon'></i>
</div>
</div>
<div id='menuEditor'>
<p class='text-info'><i class="icon icon-info-sign"></i> <?php echo $lang->custom->menuTip ?></p>
<div class='panel'>
<nav id='mainmenu'>
<ul></ul>
</nav>
<nav id='modulemenu'>
<ul></ul>
</nav>
<nav id='featurebar'>
<ul></ul>
</nav>
</div>
<div class='text-center'>
<button id='saveMenuBtn' type='button' class='btn btn-primary'><?php echo $lang->save ?></button> &nbsp;
<button type='button' class='btn' data-dismiss="modal"><?php echo $lang->close ?></button>
</div>
</div>
</div>
<script>
window.startMenu = {'module': '<?php echo $module ?>', 'method': '<?php echo $method ?>'};
</script>
<?php include '../../common/view/footer.html.php';?>