mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-12-22 15:13:42 -06:00
Refactor menu building code to support sub-menus of any depth
This commit is contained in:
parent
64399901ad
commit
00d3aaa1fd
@ -64,7 +64,7 @@ define('pgadmin.node.schema', [
|
||||
},{
|
||||
name: 'generate_erd', node: 'schema', module: this,
|
||||
applies: ['object', 'context'], callback: 'generate_erd',
|
||||
category: 'erd', priority: 5, label: gettext('ERD For Schema')
|
||||
priority: 5, label: gettext('ERD For Schema')
|
||||
}]);
|
||||
},
|
||||
can_create_schema: function(node) {
|
||||
|
@ -82,12 +82,12 @@ define('pgadmin.node.compound_trigger', [
|
||||
},{
|
||||
name: 'enable_compound_trigger', node: 'compound_trigger', module: this,
|
||||
applies: ['object', 'context'], callback: 'enable_compound_trigger',
|
||||
category: 'connect', priority: 3, label: gettext('Enable compound trigger'),
|
||||
priority: 3, label: gettext('Enable compound trigger'),
|
||||
enable : 'canCreate_with_compound_trigger_enable',
|
||||
},{
|
||||
name: 'disable_compound_trigger', node: 'compound_trigger', module: this,
|
||||
applies: ['object', 'context'], callback: 'disable_compound_trigger',
|
||||
category: 'drop', priority: 3, label: gettext('Disable compound trigger'),
|
||||
priority: 3, label: gettext('Disable compound trigger'),
|
||||
enable : 'canCreate_with_compound_trigger_disable',
|
||||
},{
|
||||
name: 'create_compound_trigger_onView', node: 'view', module: this,
|
||||
|
@ -47,7 +47,7 @@ define('pgadmin.node.foreign_key', [
|
||||
},{
|
||||
name: 'validate_foreign_key', node: 'foreign_key', module: this,
|
||||
applies: ['object', 'context'], callback: 'validate_foreign_key',
|
||||
category: 'validate', priority: 4, label: gettext('Validate foreign key'),
|
||||
priority: 4, label: gettext('Validate foreign key'),
|
||||
enable : 'is_not_valid',
|
||||
},
|
||||
]);
|
||||
|
@ -90,7 +90,7 @@ function(
|
||||
},{
|
||||
name: 'reset_table_stats', node: 'partition', module: this,
|
||||
applies: ['object', 'context'], callback: 'reset_table_stats',
|
||||
category: 'Reset', priority: 4, label: gettext('Reset Statistics'),
|
||||
priority: 4, label: gettext('Reset Statistics'),
|
||||
enable : 'canCreate',
|
||||
},{
|
||||
name: 'detach_partition', node: 'partition', module: this,
|
||||
@ -121,7 +121,7 @@ function(
|
||||
},{
|
||||
name: 'count_table_rows', node: 'partition', module: pgBrowser.Nodes['table'],
|
||||
applies: ['object', 'context'], callback: 'count_table_rows',
|
||||
category: 'Count', priority: 2, label: gettext('Count Rows'),
|
||||
priority: 2, label: gettext('Count Rows'),
|
||||
enable: true,
|
||||
}]);
|
||||
},
|
||||
|
@ -119,12 +119,12 @@ define('pgadmin.node.table', [
|
||||
},{
|
||||
name: 'count_table_rows', node: 'table', module: this,
|
||||
applies: ['object', 'context'], callback: 'count_table_rows',
|
||||
category: 'Count', priority: 2, label: gettext('Count Rows'),
|
||||
priority: 2, label: gettext('Count Rows'),
|
||||
enable: true,
|
||||
},{
|
||||
name: 'generate_erd', node: 'table', module: this,
|
||||
applies: ['object', 'context'], callback: 'generate_erd',
|
||||
category: 'erd', priority: 5, label: gettext('ERD For Table'),
|
||||
priority: 5, label: gettext('ERD For Table'),
|
||||
enable: (_, item) => {
|
||||
return !('catalog' in pgAdmin.Browser.tree.getTreeNodeHierarchy(item));
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||
|
||||
|
||||
class SchemaDiffViewCompare(SchemaDiffObjectCompare):
|
||||
view_keys_to_ignore = ['oid', 'schema', 'xmin', 'oid-2', 'setting',
|
||||
view_keys_to_ignore = ['oid', 'schema', 'xmin', 'oid-2', 'setting',
|
||||
'indrelid']
|
||||
|
||||
trigger_keys_to_ignore = ['xmin', 'tgrelid', 'tgfoid', 'tfunction',
|
||||
|
@ -87,8 +87,10 @@ define('pgadmin.node.mview', [
|
||||
@property {data} - Allow create view option on schema node or
|
||||
system view nodes.
|
||||
*/
|
||||
pgAdmin.Browser.add_menu_category(
|
||||
'refresh_mview', gettext('Refresh View'), 18, '');
|
||||
pgAdmin.Browser.add_menu_category({
|
||||
name: 'refresh_mview', label: gettext('Refresh View'), priority: 18
|
||||
});
|
||||
|
||||
pgBrowser.add_menus([{
|
||||
name: 'create_mview_on_coll', node: 'coll-mview', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
|
@ -119,7 +119,7 @@ define('pgadmin.node.database', [
|
||||
},{
|
||||
name: 'generate_erd', node: 'database', module: this,
|
||||
applies: ['object', 'context'], callback: 'generate_erd',
|
||||
category: 'erd', priority: 5, label: gettext('ERD For Database'),
|
||||
priority: 5, label: gettext('ERD For Database'),
|
||||
enable: (node) => {
|
||||
return node.allowConn;
|
||||
}
|
||||
|
@ -11,42 +11,14 @@ import pgAdmin from 'sources/pgadmin';
|
||||
import Menu, { MenuItem } from '../../../static/js/helpers/Menu';
|
||||
import getApiInstance from '../../../static/js/api_instance';
|
||||
import url_for from 'sources/url_for';
|
||||
import { getBrowser } from '../../../static/js/utils';
|
||||
import { isMac } from '../../../static/js/keyboard_shortcuts';
|
||||
|
||||
const MAIN_MENUS = [
|
||||
{ label: gettext('File'), name: 'file', id: 'mnu_file', index: 0, addSepratior: true },
|
||||
{ label: gettext('Object'), name: 'object', id: 'mnu_obj', index: 1, addSepratior: true },
|
||||
{ label: gettext('Tools'), name: 'tools', id: 'mnu_tools', index: 2, addSepratior: true },
|
||||
{ label: gettext('Help'), name: 'help', id: 'mnu_help', index: 5, addSepratior: false }
|
||||
{ label: gettext('File'), name: 'file', id: 'mnu_file', index: 0, addSeprator: true, hasDynamicMenuItems: false },
|
||||
{ label: gettext('Object'), name: 'object', id: 'mnu_obj', index: 1, addSeprator: true, hasDynamicMenuItems: true },
|
||||
{ label: gettext('Tools'), name: 'tools', id: 'mnu_tools', index: 2, addSeprator: true, hasDynamicMenuItems: false },
|
||||
{ label: gettext('Help'), name: 'help', id: 'mnu_help', index: 5, addSeprator: false, hasDynamicMenuItems: false }
|
||||
];
|
||||
|
||||
let { name: browser } = getBrowser();
|
||||
if (browser == 'Electron') {
|
||||
let controlKey = isMac() ? 'cmd' : 'ctrl';
|
||||
let fullScreenKey = isMac() ? 'F' : 'F10';
|
||||
|
||||
const RUNTIME_MENUS_OPTIONS = {
|
||||
runtime : {
|
||||
label: gettext('Runtime'),
|
||||
name: 'runtime',
|
||||
priority: 999,
|
||||
submenus: {
|
||||
configure: { label: gettext('Configure...'), name: 'configure', priority: 0, enable: true},
|
||||
view_log: { label: gettext('View log...'), name: 'view_log', priority: 1, enable: true},
|
||||
enter_full_screen: { label: gettext('Enter Full Screen'), name: 'enter_full_screen', enable: true, priority: 2, key: fullScreenKey, modifiers: isMac() ?`${controlKey}+ctrl` : controlKey},
|
||||
exit_full_screen: { label: gettext('Exit Full Screen'), name: 'exit_full_screen', enable: true, priority: 2, key: fullScreenKey, modifiers: isMac() ?`${controlKey}+ctrl` : controlKey},
|
||||
actual_size: { label: gettext('Actual Size'), name: 'actual_size', priority: 3, enable: true, key: '0', modifiers: controlKey},
|
||||
zoom_in: { label: gettext('Zoom In'), name: 'zoom_in', priority: 4, enable: true, key: '+', modifiers: controlKey},
|
||||
zoom_out: { label: gettext('Zoom Out'), name: 'zoom_out', enable: true, priority: 5, key: '-', modifiers: controlKey},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pgAdmin.Browser.RUNTIME_MENUS_OPTIONS = RUNTIME_MENUS_OPTIONS;
|
||||
}
|
||||
|
||||
|
||||
export default class MainMenuFactory {
|
||||
static electronCallbacks = {};
|
||||
|
||||
@ -75,23 +47,17 @@ export default class MainMenuFactory {
|
||||
static createMainMenus() {
|
||||
pgAdmin.Browser.MainMenus = [];
|
||||
MAIN_MENUS.forEach((_menu) => {
|
||||
let menuObj = Menu.create(_menu.name, _menu.label, _menu.id, _menu.index, _menu.addSepratior);
|
||||
let menuObj = Menu.create(_menu.name, _menu.label, _menu.id, _menu.index, _menu.addSeprator, _menu.hasDynamicMenuItems);
|
||||
pgAdmin.Browser.MainMenus.push(menuObj);
|
||||
// Don't add menuItems for Object menu as it's menuItems get changed on tree selection.
|
||||
if(_menu.name !== 'object') {
|
||||
menuObj.addMenuItems(Object.values(pgAdmin.Browser.all_menus_cache[_menu.name]));
|
||||
menuObj.getMenuItems().forEach((menuItem, index)=> {
|
||||
menuItem?.getMenuItems()?.forEach((item, indx)=> {
|
||||
item.below && menuItem?.getMenuItems().splice(indx+1, 0, MainMenuFactory.getSeparator());
|
||||
});
|
||||
if(menuItem.below) {
|
||||
menuObj.addMenuItem(MainMenuFactory.getSeparator(), index+1);
|
||||
}
|
||||
});
|
||||
menuObj.clearMenuItems();
|
||||
menuObj.addMenuItems(MainMenuFactory.createMenuItems(pgAdmin.Browser.all_menus_cache[_menu.name]));
|
||||
}
|
||||
});
|
||||
|
||||
pgAdmin.Browser.enable_disable_menus();
|
||||
// enable disable will take care of dynamic menus.
|
||||
MainMenuFactory.enableDisableMenus();
|
||||
|
||||
window.electronUI?.onMenuClick((menuName)=>{
|
||||
MainMenuFactory.electronCallbacks[menuName]?.();
|
||||
@ -135,20 +101,165 @@ export default class MainMenuFactory {
|
||||
});
|
||||
}
|
||||
|
||||
static getContextMenu(menuList) {
|
||||
Menu.sortMenus(menuList);
|
||||
return menuList;
|
||||
static enableDisableMenus(item) {
|
||||
let itemData = item ? pgAdmin.Browser.tree.itemData(item) : undefined;
|
||||
|
||||
const checkForItems = (items)=>{
|
||||
items.forEach((mitem) => {
|
||||
const subItems = mitem.getMenuItems() ?? [];
|
||||
if(subItems.length > 0) {
|
||||
checkForItems(subItems);
|
||||
} else {
|
||||
mitem.checkAndSetDisabled(itemData, item);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Non dynamic menus will be required to check whether enabled/disabled.
|
||||
pgAdmin.Browser.MainMenus.filter((m)=>(!m.hasDynamicMenuItems)).forEach((menu) => {
|
||||
checkForItems(menu.getMenuItems());
|
||||
});
|
||||
|
||||
pgAdmin.Browser.MainMenus.filter((m)=>(m.hasDynamicMenuItems)).forEach((menu) => {
|
||||
let menuItemList = MainMenuFactory.getDynamicMenu(menu.name, item, itemData);
|
||||
menu.setMenuItems(menuItemList);
|
||||
});
|
||||
|
||||
// set the context menu as well
|
||||
pgAdmin.Browser.BrowserContextMenu = MainMenuFactory.getDynamicMenu('context', item, itemData, true);
|
||||
|
||||
pgAdmin.Browser.Events.trigger('pgadmin:refresh-app-menu');
|
||||
}
|
||||
|
||||
static checkNoMenuOptionForNode(d){
|
||||
let selectedNodeFromNodes=pgAdmin.Browser.Nodes[d._type];
|
||||
static checkNoMenuOptionForNode(itemData){
|
||||
if(!itemData) {
|
||||
return true;
|
||||
}
|
||||
let selectedNodeFromNodes=pgAdmin.Browser.Nodes[itemData._type];
|
||||
let selectedNode=pgAdmin.Browser.tree.selected();
|
||||
let flag=!_.isUndefined(selectedNodeFromNodes.showMenu);
|
||||
if(flag){
|
||||
let showMenu = selectedNodeFromNodes.showMenu(d, selectedNode);
|
||||
return {flag:showMenu?false:flag,showMenu};
|
||||
} else{
|
||||
return {flag,showMenu:undefined};
|
||||
return selectedNodeFromNodes.showMenu?.(itemData, selectedNode) ?? true;
|
||||
}
|
||||
|
||||
static createMenuItems(items, skipDisabled=false, checkAndSetDisabled=()=>true) {
|
||||
let retVal = [];
|
||||
let categories = {};
|
||||
|
||||
const getNewMenuItem = (i)=>{
|
||||
const mi = MainMenuFactory.createMenuItem({...i});
|
||||
checkAndSetDisabled?.(mi);
|
||||
if(skipDisabled && mi.isDisabled) {
|
||||
return null;
|
||||
}
|
||||
return mi;
|
||||
};
|
||||
|
||||
const getMenuCategory = (catName)=>{
|
||||
let category = pgAdmin.Browser.menu_categories[catName];
|
||||
|
||||
if(!category) {
|
||||
// generate category on the fly.
|
||||
category = {
|
||||
name: catName,
|
||||
label: catName,
|
||||
priority: 10,
|
||||
};
|
||||
}
|
||||
|
||||
let cmi = categories[category.name];
|
||||
if(!cmi) {
|
||||
cmi = getNewMenuItem({...category});
|
||||
// for easily finding again, note down.
|
||||
categories[category.name] = cmi;
|
||||
}
|
||||
return cmi;
|
||||
};
|
||||
|
||||
const applySeparators = (mi)=>{
|
||||
const newItems = [];
|
||||
if(mi.above) {
|
||||
newItems.push(MainMenuFactory.getSeparator(mi.label, mi.priority));
|
||||
}
|
||||
newItems.push(mi);
|
||||
if(mi.below) {
|
||||
newItems.push(MainMenuFactory.getSeparator(mi.label, mi.priority));
|
||||
}
|
||||
return newItems;
|
||||
};
|
||||
|
||||
Object.entries(items).forEach(([k, i])=>{
|
||||
if('name' in i) {
|
||||
const mi = getNewMenuItem(i);
|
||||
if(!mi) return;
|
||||
|
||||
if(i.category??'common' != 'common') {
|
||||
const cmi = getMenuCategory(i.category);
|
||||
if(cmi) {
|
||||
cmi.addMenuItems([...applySeparators(mi)]);
|
||||
} else {
|
||||
retVal.push(...applySeparators(mi));
|
||||
}
|
||||
} else {
|
||||
retVal.push(...applySeparators(getNewMenuItem(i)));
|
||||
}
|
||||
} else {
|
||||
// Can be a category
|
||||
const cmi = getMenuCategory(k);
|
||||
if(cmi) {
|
||||
cmi.addMenuItems(MainMenuFactory.createMenuItems(i, skipDisabled, checkAndSetDisabled));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Push the category menus
|
||||
Object.values(categories).forEach((cmi)=>{
|
||||
const items = cmi.getMenuItems();
|
||||
|
||||
// if there is only one menu in the category, then no need of the category.
|
||||
if(items.length <= 1 && !cmi.single) {
|
||||
retVal = retVal.concat(items);
|
||||
return;
|
||||
}
|
||||
retVal.push(...applySeparators(cmi));
|
||||
});
|
||||
|
||||
Menu.sortMenus(retVal ?? []);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static getDynamicMenu(name, item, itemData, skipDisabled=false) {
|
||||
if(!item) {
|
||||
return [MainMenuFactory.createMenuItem({
|
||||
name: '',
|
||||
label: gettext('No object selected'),
|
||||
category: 'create',
|
||||
priority: 1,
|
||||
enable: false,
|
||||
})];
|
||||
}
|
||||
const showMenu = MainMenuFactory.checkNoMenuOptionForNode(itemData);
|
||||
if(!showMenu){
|
||||
return [MainMenuFactory.createMenuItem({
|
||||
enable : false,
|
||||
label: gettext('No menu available for this object.'),
|
||||
name:'',
|
||||
priority: 1,
|
||||
category: 'create',
|
||||
})];
|
||||
} else {
|
||||
const nodeTypeMenus = pgAdmin.Browser.all_menus_cache[name]?.[itemData._type] ?? [];
|
||||
const menuItemList = MainMenuFactory.createMenuItems(nodeTypeMenus, skipDisabled, (mi)=>{
|
||||
return mi.checkAndSetDisabled(itemData, item);
|
||||
});
|
||||
if(menuItemList.length == 0) {
|
||||
return [MainMenuFactory.createMenuItem({
|
||||
enable : false,
|
||||
label: gettext('No menu available for this object.'),
|
||||
name:'',
|
||||
priority: 1,
|
||||
category: 'create',
|
||||
})];
|
||||
}
|
||||
return menuItemList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ define('pgadmin.browser', [
|
||||
menu_categories: {
|
||||
/* name, label (pair) */
|
||||
'register': {
|
||||
name: 'register',
|
||||
label: gettext('Register'),
|
||||
priority: 1,
|
||||
/* separator above this menu */
|
||||
@ -131,6 +132,7 @@ define('pgadmin.browser', [
|
||||
single: true,
|
||||
},
|
||||
'create': {
|
||||
name: 'create',
|
||||
label: gettext('Create'),
|
||||
priority: 2,
|
||||
/* separator above this menu */
|
||||
@ -147,113 +149,9 @@ define('pgadmin.browser', [
|
||||
scripts[n].push({'name': m, 'path': p, loaded: false});
|
||||
},
|
||||
masterpass_callback_queue: [],
|
||||
getMenuList: function(name, item, d, skipDisabled=false) {
|
||||
let obj = this;
|
||||
//This 'checkNoMenuOptionForNode' function will check if showMenu flag is present or not for selected node
|
||||
let {flag,showMenu}=MainMenuFactory.checkNoMenuOptionForNode(d);
|
||||
if(flag){
|
||||
if(showMenu===false){
|
||||
return [MainMenuFactory.createMenuItem({
|
||||
enable : false,
|
||||
label: gettext('No menu available for this object.'),
|
||||
name:'',
|
||||
priority: 1,
|
||||
category: 'create',
|
||||
})];
|
||||
}
|
||||
}else{
|
||||
let category = {
|
||||
'common': []
|
||||
};
|
||||
const nodeTypeMenus = obj.all_menus_cache[name][d._type];
|
||||
for(let key of Object.keys(nodeTypeMenus)) {
|
||||
let menuItem = nodeTypeMenus[key];
|
||||
let menuCategory = menuItem.category ?? 'common';
|
||||
category[menuCategory] = category[menuCategory] ?? [];
|
||||
category[menuCategory].push(menuItem);
|
||||
}
|
||||
let menuItemList = [];
|
||||
|
||||
for(let c in category) {
|
||||
if((c in obj.menu_categories || category[c].length > 1) && c != 'common' ) {
|
||||
let allMenuItemsDisabled = true;
|
||||
category[c].forEach((mi)=> {
|
||||
mi.checkAndSetDisabled(d, item);
|
||||
if(allMenuItemsDisabled) {
|
||||
allMenuItemsDisabled = mi.isDisabled;
|
||||
}
|
||||
});
|
||||
|
||||
const categoryMenuOptions = obj.menu_categories[c];
|
||||
let label = categoryMenuOptions?.label ?? c;
|
||||
let priority = categoryMenuOptions?.priority ?? 10;
|
||||
|
||||
if(categoryMenuOptions?.above) {
|
||||
menuItemList.push(MainMenuFactory.getSeparator(label, priority));
|
||||
}
|
||||
if((!allMenuItemsDisabled && skipDisabled) || !skipDisabled) {
|
||||
let _menuItem = MainMenuFactory.createMenuItem({
|
||||
name: c,
|
||||
label: label,
|
||||
module: c,
|
||||
category: c,
|
||||
menu_items: category[c],
|
||||
priority: priority
|
||||
});
|
||||
|
||||
menuItemList.push(_menuItem);
|
||||
}
|
||||
if(categoryMenuOptions?.below) {
|
||||
menuItemList.push(MainMenuFactory.getSeparator(label, priority));
|
||||
}
|
||||
} else {
|
||||
category[c].forEach((c)=> {
|
||||
c.checkAndSetDisabled(d, item);
|
||||
});
|
||||
|
||||
category[c].forEach((m)=> {
|
||||
if(!skipDisabled || (skipDisabled && !m.isDisabled)) {
|
||||
menuItemList.push(m);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return menuItemList;
|
||||
}
|
||||
},
|
||||
// Enable/disable menu options
|
||||
enable_disable_menus: function(item) {
|
||||
let obj = this;
|
||||
let d = item ? obj.tree.itemData(item) : undefined;
|
||||
|
||||
// All menus (except for the object menus) are already present.
|
||||
// They will just require to check, whether they are
|
||||
// enabled/disabled.
|
||||
pgBrowser.MainMenus.filter((m)=>m.name != 'object').forEach((menu) => {
|
||||
menu.menuItems.forEach((mitem) => {
|
||||
mitem.checkAndSetDisabled(d, item);
|
||||
});
|
||||
});
|
||||
|
||||
// Create the object menu dynamically
|
||||
let objectMenu = pgBrowser.MainMenus.find((menu) => menu.name == 'object');
|
||||
if (item && obj.all_menus_cache['object']?.[d._type]) {
|
||||
let menuItemList = obj.getMenuList('object', item, d);
|
||||
objectMenu && MainMenuFactory.refreshMainMenuItems(objectMenu, menuItemList);
|
||||
let ctxMenuList = obj.getMenuList('context', item, d, true);
|
||||
obj.BrowserContextMenu = MainMenuFactory.getContextMenu(ctxMenuList);
|
||||
} else {
|
||||
objectMenu && MainMenuFactory.refreshMainMenuItems(objectMenu, [
|
||||
MainMenuFactory.createMenuItem({
|
||||
name: '',
|
||||
label: gettext('No object selected'),
|
||||
category: 'create',
|
||||
priority: 1,
|
||||
enable: false,
|
||||
})
|
||||
]);
|
||||
}
|
||||
MainMenuFactory.enableDisableMenus(item);
|
||||
},
|
||||
init: function() {
|
||||
let obj=this;
|
||||
@ -414,29 +312,28 @@ define('pgadmin.browser', [
|
||||
});
|
||||
},
|
||||
|
||||
add_menu_category: function(
|
||||
id, label, priority, icon, above_separator, below_separator, single
|
||||
) {
|
||||
this.menu_categories[id] = {
|
||||
label: label,
|
||||
priority: priority,
|
||||
icon: icon,
|
||||
above: (above_separator === true),
|
||||
below: (below_separator === true),
|
||||
single: single,
|
||||
add_menu_category: function({name, ...options}) {
|
||||
this.menu_categories[name] = {
|
||||
label: '(No Label)',
|
||||
priority: 10,
|
||||
icon: '',
|
||||
above: false,
|
||||
below: false,
|
||||
parent: null,
|
||||
isCategory: true,
|
||||
...options,
|
||||
};
|
||||
},
|
||||
|
||||
// Add menus of module/extension at appropriate menu
|
||||
add_menus: function(menus) {
|
||||
let pgMenu = this.all_menus_cache;
|
||||
const self = this;
|
||||
let allMenus = this.all_menus_cache;
|
||||
|
||||
_.each(menus, function(m) {
|
||||
_.each(m.applies, function(a) {
|
||||
/* We do support menu type only from this list */
|
||||
if(['context', 'file', 'edit', 'object','management', 'tools', 'help'].indexOf(a) > -1){
|
||||
let _menus;
|
||||
|
||||
// If current node is not visible in browser tree
|
||||
// then return from here
|
||||
if(!checkNodeVisibility(m.node)) {
|
||||
@ -448,16 +345,19 @@ define('pgadmin.browser', [
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pgMenu[a] = pgMenu[a] || {};
|
||||
if (_.isString(m.node)) {
|
||||
_menus = pgMenu[a][m.node] = pgMenu[a][m.node] || {};
|
||||
} else if (_.isString(m.category)) {
|
||||
_menus = pgMenu[a][m.category] = pgMenu[a][m.category] || {};
|
||||
}
|
||||
else {
|
||||
_menus = pgMenu[a];
|
||||
}
|
||||
const getFullPath = (currPath, currMenu)=>{
|
||||
if(currMenu.node) {
|
||||
return currPath.concat([currMenu.node]);
|
||||
} else if(currMenu.category??'common' != 'common') {
|
||||
const currCat = self.menu_categories[currMenu.category];
|
||||
if(currCat?.category) {
|
||||
return getFullPath(currPath.concat([currMenu.category]), currCat);
|
||||
}
|
||||
return [currMenu.category].concat(currPath);
|
||||
} else {
|
||||
return currPath;
|
||||
}
|
||||
};
|
||||
|
||||
let get_menuitem_obj = function(_m) {
|
||||
let enable = _m.enable;
|
||||
@ -474,7 +374,7 @@ define('pgadmin.browser', [
|
||||
};
|
||||
}
|
||||
|
||||
return MainMenuFactory.createMenuItem({
|
||||
return {
|
||||
name: _m.name,
|
||||
label: _m.label,
|
||||
module: _m.module,
|
||||
@ -490,20 +390,19 @@ define('pgadmin.browser', [
|
||||
checked: _m.checked,
|
||||
below: _m.below,
|
||||
applies: _m.applies,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
if (!_.has(_menus, m.name)) {
|
||||
_menus[m.name] = get_menuitem_obj(m);
|
||||
const menuPath = [a].concat(getFullPath([], m)).concat([m.name]);
|
||||
const _menus = _.set(allMenus, menuPath, get_menuitem_obj(m));
|
||||
|
||||
if(m.menu_items) {
|
||||
let sub_menu_items = [];
|
||||
if(m.menu_items) {
|
||||
let sub_menu_items = [];
|
||||
|
||||
for(let mnu_val of m.menu_items) {
|
||||
sub_menu_items.push(get_menuitem_obj(mnu_val));
|
||||
}
|
||||
_menus[m.name]['menu_items'] = sub_menu_items;
|
||||
for(let mnu_val of m.menu_items) {
|
||||
sub_menu_items.push(get_menuitem_obj(mnu_val));
|
||||
}
|
||||
_menus[m.name]['menu_items'] = sub_menu_items;
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
|
@ -136,7 +136,8 @@ export function getNodeAjaxOptions(url, nodeObj, treeNodeInfo, itemNodeData, par
|
||||
}
|
||||
|
||||
/* Get the nodes list based on current selected node id */
|
||||
export function getNodeListById(nodeObj, treeNodeInfo, itemNodeData, params={}, filter=()=>true) {
|
||||
export function getNodeListById(nodeObj, treeNodeInfo, itemNodeData, params={}, filter=()=>true, postTransform=(res)=>res) {
|
||||
nodeObj = typeof(nodeObj) == 'string' ? pgAdmin.Browser.Nodes[nodeObj] : nodeObj;
|
||||
/* Transform the result to add image details */
|
||||
const transform = (rows) => {
|
||||
let res = [];
|
||||
@ -158,7 +159,7 @@ export function getNodeListById(nodeObj, treeNodeInfo, itemNodeData, params={},
|
||||
}
|
||||
});
|
||||
|
||||
return res;
|
||||
return postTransform(res);
|
||||
};
|
||||
|
||||
return getNodeAjaxOptions('nodes', nodeObj, treeNodeInfo, itemNodeData, params, transform);
|
||||
|
@ -67,7 +67,7 @@ export default function AppMenuBar() {
|
||||
pgAdmin.Browser.Events.on('pgadmin:enable-disable-menu-items', _.debounce(()=>{
|
||||
forceUpdate();
|
||||
}, 100));
|
||||
pgAdmin.Browser.Events.on('pgadmin:refresh-menu-item', _.debounce(()=>{
|
||||
pgAdmin.Browser.Events.on('pgadmin:refresh-app-menu', _.debounce(()=>{
|
||||
forceUpdate();
|
||||
}, 100));
|
||||
}, []);
|
||||
@ -95,6 +95,18 @@ export default function AppMenuBar() {
|
||||
|
||||
const userMenuInfo = pgAdmin.Browser.utils.userMenuInfo;
|
||||
|
||||
const getPgMenu = (menu)=>{
|
||||
return menu.getMenuItems()?.map((menuItem, i)=>{
|
||||
const submenus = menuItem.getMenuItems();
|
||||
if(submenus) {
|
||||
return <PgSubMenu key={menuItem.label} label={menuItem.label}>
|
||||
{getPgMenu(menuItem)}
|
||||
</PgSubMenu>;
|
||||
}
|
||||
return getPgMenuItem(menuItem, i);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledBox data-test="app-menu-bar">
|
||||
<div className='AppMenuBar-logo' />
|
||||
@ -106,17 +118,7 @@ export default function AppMenuBar() {
|
||||
label={menu.label}
|
||||
key={menu.name}
|
||||
>
|
||||
{menu.getMenuItems().map((menuItem, i)=>{
|
||||
const submenus = menuItem.getMenuItems();
|
||||
if(submenus) {
|
||||
return <PgSubMenu key={menuItem.label} label={menuItem.label}>
|
||||
{submenus.map((submenuItem, si)=>{
|
||||
return getPgMenuItem(submenuItem, si);
|
||||
})}
|
||||
</PgSubMenu>;
|
||||
}
|
||||
return getPgMenuItem(menuItem, i);
|
||||
})}
|
||||
{getPgMenu(menu)}
|
||||
</PgMenu>
|
||||
);
|
||||
})}
|
||||
|
@ -10,17 +10,18 @@ import _ from 'lodash';
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
export default class Menu {
|
||||
constructor(name, label, id, index, addSepratior) {
|
||||
constructor(name, label, id, index, addSeprator, hasDynamicMenuItems) {
|
||||
this.label = label;
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.index = index || 1;
|
||||
this.menuItems = [];
|
||||
this.addSepratior = addSepratior || false;
|
||||
this.addSeprator = addSeprator || false;
|
||||
this.hasDynamicMenuItems = hasDynamicMenuItems;
|
||||
}
|
||||
|
||||
static create(name, label, id, index, addSepratior) {
|
||||
let menuObj = new Menu(name, label, id, index, addSepratior);
|
||||
static create(name, label, id, index, addSeprator, hasDynamicMenuItems) {
|
||||
let menuObj = new Menu(name, label, id, index, addSeprator, hasDynamicMenuItems);
|
||||
return menuObj;
|
||||
}
|
||||
|
||||
@ -30,7 +31,7 @@ export default class Menu {
|
||||
label: this.label,
|
||||
name: this.name,
|
||||
index: this.index,
|
||||
addSepratior: this.addSepratior,
|
||||
addSeprator: this.addSeprator,
|
||||
};
|
||||
}
|
||||
|
||||
@ -41,13 +42,10 @@ export default class Menu {
|
||||
this.menuItems.splice(index, 0, menuItem);
|
||||
} else {
|
||||
this.menuItems.push(menuItem);
|
||||
Menu.sortMenus(this.menuItems);
|
||||
}
|
||||
} else {
|
||||
throw new Error(gettext('Invalid MenuItem instance'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
addMenuItems(menuItems) {
|
||||
@ -59,7 +57,6 @@ export default class Menu {
|
||||
item.menu_items.forEach((i)=> {
|
||||
i.parentMenu = item;
|
||||
});
|
||||
Menu.sortMenus(item.menu_items);
|
||||
}
|
||||
} else {
|
||||
let subItems = Object.values(item);
|
||||
@ -88,16 +85,16 @@ export default class Menu {
|
||||
|
||||
setMenuItems(menuItems) {
|
||||
this.menuItems = menuItems;
|
||||
Menu.sortMenus(this.menuItems);
|
||||
}
|
||||
|
||||
this.menuItems.forEach((item)=> {
|
||||
if(item?.menu_items?.length > 0) {
|
||||
Menu.sortMenus(item.menu_items);
|
||||
}
|
||||
});
|
||||
clearMenuItems() {
|
||||
this.menuItems = [];
|
||||
}
|
||||
|
||||
static sortMenus(menuItems) {
|
||||
if(!menuItems || menuItems.length <=0) {
|
||||
return;
|
||||
}
|
||||
// Sort by alphanumeric ordered first
|
||||
menuItems.sort(function (a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
@ -107,6 +104,10 @@ export default class Menu {
|
||||
menuItems.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
|
||||
menuItems.forEach((mi)=>{
|
||||
Menu.sortMenus(mi.getMenuItems());
|
||||
});
|
||||
}
|
||||
|
||||
getMenuItems() {
|
||||
@ -117,9 +118,9 @@ export default class Menu {
|
||||
|
||||
export class MenuItem {
|
||||
constructor(options, onDisableChange) {
|
||||
let menu_opts = [
|
||||
let allowedOptions = [
|
||||
'name', 'label', 'priority', 'module', 'callback', 'data', 'enable',
|
||||
'category', 'target', 'url', 'node',
|
||||
'category', 'target', 'url', 'node', 'single',
|
||||
'checked', 'below', 'menu_items', 'is_checkbox', 'action', 'applies', 'is_native_only', 'type',
|
||||
];
|
||||
let defaults = {
|
||||
@ -127,7 +128,7 @@ export class MenuItem {
|
||||
target: '_self',
|
||||
enable: true,
|
||||
};
|
||||
_.extend(this, defaults, _.pick(options, menu_opts));
|
||||
_.extend(this, defaults, _.pick(options, allowedOptions));
|
||||
if (!this.callback) {
|
||||
this.callback = (item) => {
|
||||
if (item.url != '#') {
|
||||
@ -159,6 +160,11 @@ export class MenuItem {
|
||||
this.checked = isChecked;
|
||||
}
|
||||
|
||||
addMenuItems(items) {
|
||||
this.menu_items = this.menu_items ?? [];
|
||||
this.menu_items = this.menu_items.concat(items);
|
||||
}
|
||||
|
||||
getMenuItems() {
|
||||
return this.menu_items;
|
||||
}
|
||||
|
@ -163,7 +163,10 @@ export default class SQLEditor {
|
||||
});
|
||||
}
|
||||
|
||||
pgBrowser.add_menu_category('view_data', gettext('View/Edit Data'), 100, '');
|
||||
pgBrowser.add_menu_category({
|
||||
name: 'view_data', label: gettext('View/Edit Data'), priority: 100
|
||||
});
|
||||
|
||||
pgBrowser.add_menus(menus);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user