diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
index 7a8a693aa..5e31000c1 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
@@ -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) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
index 968b553c3..d7996fa85 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
@@ -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,
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
index 729b307de..acb7a5aa9 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
@@ -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',
},
]);
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
index a33859fab..cf218a6ca 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
@@ -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,
}]);
},
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
index 01fbf1dd6..528c3221d 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
@@ -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));
}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/schema_diff_view_utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/schema_diff_view_utils.py
index 3aaa19cf4..fba3dac18 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/schema_diff_view_utils.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/schema_diff_view_utils.py
@@ -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',
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
index e07dbd5f2..0edadcbd6 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
@@ -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',
diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
index f1823a2ac..7b80a118b 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
@@ -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;
}
diff --git a/web/pgadmin/browser/static/js/MainMenuFactory.js b/web/pgadmin/browser/static/js/MainMenuFactory.js
index 80f697f7f..eb3dc9cce 100644
--- a/web/pgadmin/browser/static/js/MainMenuFactory.js
+++ b/web/pgadmin/browser/static/js/MainMenuFactory.js
@@ -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;
}
}
}
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 96bc29705..8bbdab789 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -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(
diff --git a/web/pgadmin/browser/static/js/node_ajax.js b/web/pgadmin/browser/static/js/node_ajax.js
index 4a1fc112c..877e645b9 100644
--- a/web/pgadmin/browser/static/js/node_ajax.js
+++ b/web/pgadmin/browser/static/js/node_ajax.js
@@ -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);
diff --git a/web/pgadmin/static/js/AppMenuBar.jsx b/web/pgadmin/static/js/AppMenuBar.jsx
index c83b04ac9..9f4164bf2 100644
--- a/web/pgadmin/static/js/AppMenuBar.jsx
+++ b/web/pgadmin/static/js/AppMenuBar.jsx
@@ -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
+ {getPgMenu(menuItem)}
+ ;
+ }
+ return getPgMenuItem(menuItem, i);
+ });
+ };
+
return (
@@ -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
- {submenus.map((submenuItem, si)=>{
- return getPgMenuItem(submenuItem, si);
- })}
- ;
- }
- return getPgMenuItem(menuItem, i);
- })}
+ {getPgMenu(menu)}
);
})}
diff --git a/web/pgadmin/static/js/helpers/Menu.js b/web/pgadmin/static/js/helpers/Menu.js
index 30ff26d8a..3db5aeb06 100644
--- a/web/pgadmin/static/js/helpers/Menu.js
+++ b/web/pgadmin/static/js/helpers/Menu.js
@@ -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;
}
diff --git a/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js b/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
index a21bc2569..0795f949a 100644
--- a/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
+++ b/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
@@ -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);
}