* improve custom menu UI.
This commit is contained in:
@@ -156,7 +156,7 @@ $lang->index->menu->project = "浏览{$lang->projectCommon}|project|browse";
|
||||
$lang->my = new stdclass();
|
||||
$lang->my->menu = new stdclass();
|
||||
|
||||
$lang->my->menu->account = '<span id="myname"><i class="icon-user"></i> %s' . $lang->arrow . '</span>';
|
||||
$lang->my->menu->account = array('link' => '<span id="myname"><i class="icon-user"></i> %s' . $lang->arrow . '</span>', 'fixed' => true);
|
||||
$lang->my->menu->index = '首页|my|index';
|
||||
$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo');
|
||||
$lang->my->menu->task = array('link' => '任务|my|task|', 'subModule' => 'task');
|
||||
@@ -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', 'fixed' => true);
|
||||
$lang->product->menu->index = '首页|product|index|locate=no';
|
||||
$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s';
|
||||
|
||||
@@ -483,7 +483,7 @@ class commonModel extends model
|
||||
/* Cycling to print every sub menus. */
|
||||
foreach($menu as $menuItem)
|
||||
{
|
||||
|
||||
if($menuItem->hidden) continue;
|
||||
/* Init the these vars. */
|
||||
if($menuItem->link)
|
||||
{
|
||||
|
||||
@@ -193,18 +193,27 @@ class custom extends control
|
||||
if($_POST)
|
||||
{
|
||||
$account = $this->app->user->account;
|
||||
$menu = $_POST['menu'];
|
||||
$menus = $_POST['menus'];
|
||||
|
||||
if(empty($menus)) $this->send(array('result' => 'fail', 'message' => $this->lang->custom->saveFail));
|
||||
|
||||
if(empty($method))
|
||||
if(is_array($menus))
|
||||
{
|
||||
$this->loadModel('setting')->setItem("$account.menucustom.$module", $menu);
|
||||
foreach ($menus as $menu)
|
||||
{
|
||||
$menu = json_decode($menu);
|
||||
$this->custom->saveCustomMenu($menu->value, $menu->module, $menu->method);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$configKey = 'menucustom' . $module;
|
||||
$this->loadModel('setting')->setItem("$account.$configKey.$method", $menu);
|
||||
if(!empty($_POST['module'])) $module = $_POST['module'];
|
||||
if(!empty($_POST['method'])) $method = $_POST['method'];
|
||||
|
||||
$this->custom->saveCustomMenu($menus, $module, $method);
|
||||
}
|
||||
$this->send(array('result' => 'success', 'menu' => $menu));
|
||||
|
||||
$this->send(array('result' => 'success'));
|
||||
}
|
||||
|
||||
if($this->viewType === 'json')
|
||||
@@ -225,7 +234,7 @@ class custom extends control
|
||||
{
|
||||
$menu = !empty($method) ? customModel::getFeatureMenu($module, $method) : customModel::getModuleMenu($module, true);
|
||||
}
|
||||
$this->send(array('result' => $menu ? 'success' : 'fail', 'menu' => $menu));
|
||||
die(json_encode(array('result' => $menu ? 'success' : 'fail', 'menu' => $menu), JSON_HEX_QUOT | JSON_HEX_APOS));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+150
-41
@@ -13,8 +13,29 @@ $(function()
|
||||
'feature': {}
|
||||
};
|
||||
|
||||
var updateMenu = function($menu, items)
|
||||
var updateConfig = function($menu)
|
||||
{
|
||||
var moduleName = $menu.data('module'), methodName = $menu.data('method');
|
||||
var menu = [];
|
||||
$menu.children('.nav').children('li:not(.drag-shadow)').each(function()
|
||||
{
|
||||
var $e = $(this);
|
||||
var item = $e.children('a').data('menu');
|
||||
item.order = $e.attr('data-order');
|
||||
menu.push(item);
|
||||
});
|
||||
if(moduleName === 'main') menuConfig.main = menu;
|
||||
else if(methodName) menuConfig['feature'][moduleName][methodName] = menu;
|
||||
else menuConfig['module'][moduleName] = menu;
|
||||
}
|
||||
|
||||
var updateMenu = function(moduleName, methodName, items)
|
||||
{
|
||||
var $menu = moduleName === 'main' ? $mainMenu : (methodName ? $featureMenu : $moduleMenu);
|
||||
var items = items || (moduleName === 'main' ? menuConfig.main : (methodName ? menuConfig['feature'][moduleName][methodName] : menuConfig['module'][moduleName]));
|
||||
|
||||
$menu.data({'module': moduleName, 'method': methodName});
|
||||
|
||||
if(items)
|
||||
{
|
||||
var $nav = $('<ul class="nav"/>');
|
||||
@@ -24,7 +45,10 @@ $(function()
|
||||
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();
|
||||
$nav.sortable({finish: function(e)
|
||||
{
|
||||
updateConfig(e.element.closest('nav'));
|
||||
}});
|
||||
$menu.children('ul').replaceWith($nav);
|
||||
}
|
||||
else
|
||||
@@ -43,71 +67,125 @@ $(function()
|
||||
$moduleMenu.find('li[data-id="' + methodName + '"]').addClass('active');
|
||||
};
|
||||
|
||||
var loadData = function(moduleName, methodName, type)
|
||||
var loadData = function(moduleName, methodName, type, callback)
|
||||
{
|
||||
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'])
|
||||
if(menu['main'] && !menuConfig['main'])
|
||||
{
|
||||
updateMenu($mainMenu, menu['main']);
|
||||
menuConfig['main'] = menu['main'];
|
||||
}
|
||||
if(menu['module'])
|
||||
if(menu['module'] && !menuConfig['module'][moduleName])
|
||||
{
|
||||
updateMenu($moduleMenu, menu['module']);
|
||||
menuConfig['module'][moduleName] = menu['module'];
|
||||
}
|
||||
if(menu['feature'] !== undefined)
|
||||
if(menu['feature'] !== undefined && (!menuConfig['feature'][moduleName] || menuConfig['feature'][moduleName][methodName] === undefined))
|
||||
{
|
||||
updateMenu($featureMenu, menu['feature']);
|
||||
if(!menuConfig['feature'][moduleName]) menuConfig['feature'][moduleName] = {};
|
||||
menuConfig['feature'][moduleName][methodName] = menu['feature'];
|
||||
}
|
||||
activeCurrent(moduleName, methodName);
|
||||
callback && callback(true, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback && callback(false, data);
|
||||
}
|
||||
activeCurrent(moduleName, methodName);
|
||||
$loadingIcon.removeClass('active');
|
||||
}, 'json');
|
||||
};
|
||||
|
||||
$menuEditor.on('mouseenter', '.nav > li > a', function()
|
||||
var formatMenuConfig = function(items)
|
||||
{
|
||||
// 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');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return $.map(items, function(item)
|
||||
{
|
||||
var data = {name: item.name, order: parseInt(item.order)};
|
||||
if(item.hidden) data.hidden = true;
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
$menuEditor.on('mouseenter', '.nav > li:not(.drag-shadow) > a', function()
|
||||
{
|
||||
var $a = $(this);
|
||||
var item = $a.data('menu');
|
||||
var $menu = $a.closest('nav');
|
||||
|
||||
if($menu.is('#mainmenu'))
|
||||
{
|
||||
var moduleName = item.name;
|
||||
if(moduleName !== currentModule)
|
||||
{
|
||||
var methodName = item.link['method'];
|
||||
if(menuConfig['module'][moduleName])
|
||||
{
|
||||
updateMenu(moduleName);
|
||||
if(menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined)
|
||||
{
|
||||
updateMenu(moduleName, methodName);
|
||||
activeCurrent(moduleName, methodName);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadData(moduleName, methodName, 'all', function(result)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
updateMenu(moduleName, methodName);
|
||||
activeCurrent(moduleName, methodName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
loadData(moduleName, methodName, 'all', function(result)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
updateMenu(moduleName);
|
||||
updateMenu(moduleName, methodName);
|
||||
activeCurrent(moduleName, methodName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if($menu.is('#modulemenu'))
|
||||
{
|
||||
var moduleName = currentModule;
|
||||
var methodName = item.name;
|
||||
if(methodName !== currentMethod)
|
||||
{
|
||||
if(menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined)
|
||||
{
|
||||
updateMenu(moduleName, methodName);
|
||||
activeCurrent(moduleName, methodName);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadData(moduleName, methodName, 'all', function(result)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
updateMenu(moduleName, methodName);
|
||||
activeCurrent(moduleName, methodName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).on('click', '.nav > li > a', function()
|
||||
{
|
||||
var $a = $(this);
|
||||
var item = $a.data('menu');
|
||||
item.hidden = !!!item.hidden;
|
||||
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'] : '';
|
||||
@@ -116,14 +194,45 @@ $(function()
|
||||
moduleName = currentModule;
|
||||
methodName = item.name;
|
||||
}
|
||||
$a.parent().toggleClass('menu-hidden');
|
||||
$a.parent().toggleClass('menu-hidden', item.hidden);
|
||||
updateConfig($menu);
|
||||
});
|
||||
|
||||
$('#saveMenuBtn').click(function()
|
||||
{
|
||||
console.log('save', menuConfig);
|
||||
var postData = [{'module': 'main', value: formatMenuConfig(menuConfig.main)}];
|
||||
$.each(menuConfig['module'], function(moduleName, items)
|
||||
{
|
||||
postData.push({'module': moduleName, value: formatMenuConfig(items)});
|
||||
});
|
||||
|
||||
$.each(menuConfig['feature'], function(moduleName, feature)
|
||||
{
|
||||
if(!feature) return;
|
||||
$.each(feature, function(methodName, items)
|
||||
{
|
||||
if(items) postData.push({'module': moduleName, 'method': methodName, value: formatMenuConfig(items)});
|
||||
});
|
||||
});
|
||||
|
||||
postData = $.map(postData, JSON.stringify);
|
||||
|
||||
$.post(createLink('custom', 'menu'), {menus: postData}, function(data)
|
||||
{
|
||||
if(data.result === 'success') window.parent.location.reload()
|
||||
if(data.message) alert(data.message);
|
||||
}, 'json').error(function(e) {alert(lang.timeout); console.log(e);});
|
||||
}).on('mouseenter', function() {$menuEditor.addClass('preview')})
|
||||
.on('mouseout', function() {$menuEditor.removeClass('preview')});
|
||||
|
||||
loadData(currentModule, currentMethod, 'all');
|
||||
loadData(currentModule, currentMethod, 'all', function(result)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
updateMenu('main');
|
||||
updateMenu(currentModule);
|
||||
updateMenu(currentModule, currentMethod);
|
||||
activeCurrent(currentModule, currentMethod);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,4 +80,5 @@ $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.';
|
||||
$lang->custom->menuTip = 'Click menu item to toggle display status, drag and drop to change display order.';
|
||||
$lang->custom->saveFail = 'Save failed.';
|
||||
|
||||
@@ -80,4 +80,5 @@ $lang->custom->productproject->relation['1_1'] = '项目 - 迭代';
|
||||
|
||||
$lang->custom->productproject->notice = '请根据实际情况选择适合自己团队的概念。';
|
||||
|
||||
$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。';
|
||||
$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。';
|
||||
$lang->custom->saveFail = '保存失败!';
|
||||
|
||||
+31
-4
@@ -173,7 +173,6 @@ class customModel extends model
|
||||
$method = '';
|
||||
$float = '';
|
||||
$fixed = '';
|
||||
$hidden = $isSetMenuConfig && $menuConfigMap[$name] && $menuConfigMap[$name]->hidden;
|
||||
|
||||
$link = is_array($item) ? $item['link'] : $item;
|
||||
if(strpos($link, '|') !== false)
|
||||
@@ -208,11 +207,12 @@ class customModel extends model
|
||||
$fixed = $item['fixed'];
|
||||
}
|
||||
|
||||
$hidden = !$fixed && $isSetMenuConfig && $menuConfigMap[$name] && $menuConfigMap[$name]->hidden;
|
||||
|
||||
$menuItem = new stdclass();
|
||||
$menuItem->name = $name;
|
||||
$menuItem->link = $itemLink;
|
||||
$menuItem->text = $label;
|
||||
$menuItem->source = $item;
|
||||
$menuItem->order = $isSetMenuConfig && $menuConfigMap[$name] && isset($menuConfigMap[$name]->order) ? $menuConfigMap[$name]->order : $order++;
|
||||
if($float) $menuItem->float = $float;
|
||||
if($fixed) $menuItem->fixed = $fixed;
|
||||
@@ -273,12 +273,39 @@ class customModel extends model
|
||||
{
|
||||
global $app, $lang, $config;
|
||||
$app->loadLang($module);
|
||||
$configKey = 'menucustom' . $module;
|
||||
|
||||
$menuConfig = $config->$configKey->$method;
|
||||
$configKey = 'feature_' . $module . '_' . $method;
|
||||
$menuConfig = $config->menucustom->$configKey;
|
||||
if(!empty($menuConfig)) $menuConfig = json_decode($menuConfig);
|
||||
$allMenu = $lang->$module->featurebar[$method];
|
||||
|
||||
return $allMenu ? self::buildMenuConfig($allMenu, $menuConfig) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save custom menu to config
|
||||
* @param string $menu
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveCustomMenu($menu, $module, $method)
|
||||
{
|
||||
$account = $this->app->user->account;
|
||||
$settingKey = '';
|
||||
|
||||
if(!is_string($menu)) $menu = json_encode($menu);
|
||||
|
||||
if(empty($method))
|
||||
{
|
||||
$settingKey = "$account.common.menucustom.$module";
|
||||
}
|
||||
else
|
||||
{
|
||||
$settingKey = "$account.common.menucustom.feature_$module_$method";
|
||||
}
|
||||
|
||||
$this->loadModel('setting')->setItem($settingKey, $menu);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -1795,10 +1795,15 @@ function initMainMenu()
|
||||
selector: 'li:not(.custom-item)',
|
||||
finish: function(e)
|
||||
{
|
||||
var menu = e.list.map(function(){return $(this).data('id');}).get();
|
||||
$.post(createLink('custom', 'menu'), {menu: menu.join(',')}, function(data)
|
||||
var menu = [];
|
||||
e.list.each(function()
|
||||
{
|
||||
}, 'json');
|
||||
var $e = $(this);
|
||||
menu.push({name: $e.data('id'), order: $e.attr('data-order')});
|
||||
});
|
||||
$.post(createLink('custom', 'menu'), {menus: JSON.stringify(menu), "module": 'main'}, function(data)
|
||||
{
|
||||
}, 'json').error(function() {alert(lang.timeout)});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user