diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index be5dffa0a4..9366dac90b 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -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');
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 3341a9a09b..8c0c4f7274 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -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');
diff --git a/module/common/model.php b/module/common/model.php
index 0b438c0354..7325dffc1e 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -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 "
$menuItem->text\n";
}
- $customLink = helper::createLink('custom', 'menu');
- echo "";
+ $customLink = helper::createLink('custom', 'menu', "module={$app->getModuleName()}&method={$app->getMethodName()}", '', true);
+ echo "";
echo "\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'];
}
diff --git a/module/custom/control.php b/module/custom/control.php
index 1b60f57577..5b66b4daee 100644
--- a/module/custom/control.php
+++ b/module/custom/control.php
@@ -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
diff --git a/module/custom/css/menu.css b/module/custom/css/menu.css
new file mode 100644
index 0000000000..eeef639254
--- /dev/null
+++ b/module/custom/css/menu.css
@@ -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;}
diff --git a/module/custom/js/menu.js b/module/custom/js/menu.js
new file mode 100644
index 0000000000..9efc9e6f2c
--- /dev/null
+++ b/module/custom/js/menu.js
@@ -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 = $('');
+ $.each(items, function(idx, item)
+ {
+ if(!item.text || item.fixed) return;
+ var $a = $('').html(item.text).data('menu', item).append('');
+ $('').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');
+});
diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php
index 8825d81b5a..49219bd92b 100644
--- a/module/custom/lang/en.php
+++ b/module/custom/lang/en.php
@@ -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.';
diff --git a/module/custom/lang/zh-cn.php b/module/custom/lang/zh-cn.php
index 787dfd63ab..a96e360e41 100644
--- a/module/custom/lang/zh-cn.php
+++ b/module/custom/lang/zh-cn.php
@@ -79,3 +79,5 @@ $lang->custom->productproject->relation['0_1'] = '产品 - 迭代';
$lang->custom->productproject->relation['1_1'] = '项目 - 迭代';
$lang->custom->productproject->notice = '请根据实际情况选择适合自己团队的概念。';
+
+$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。';
diff --git a/module/custom/model.php b/module/custom/model.php
index 157a252ed3..ac7293d1de 100644
--- a/module/custom/model.php
+++ b/module/custom/model.php
@@ -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;
diff --git a/module/custom/view/menu.html.php b/module/custom/view/menu.html.php
new file mode 100644
index 0000000000..4928b87083
--- /dev/null
+++ b/module/custom/view/menu.html.php
@@ -0,0 +1,42 @@
+
+ * @package user
+ * @version $Id: edit.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+