mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added native menu support in desktop mode. #5503
This commit is contained in:
@@ -7,11 +7,16 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import React from 'react';
|
||||
import { generateNodeUrl } from './node_ajax';
|
||||
import { getBrowser } from '../../../static/js/utils';
|
||||
import createMainMenus, {refreshMainMenuItems, MainMenuItemFactory} from './main_menu';
|
||||
import { getContextMenu} from './new_menu';
|
||||
import _ from 'lodash';
|
||||
import Notify, {initializeModalProvider, initializeNotifier} from '../../../static/js/helpers/Notifier';
|
||||
import { checkMasterPassword } from '../../../static/js/Dialogs/index';
|
||||
import { pgHandleItemError } from '../../../static/js/utils';
|
||||
import { Search } from './quick_search/trigger_search';
|
||||
|
||||
define('pgadmin.browser', [
|
||||
'sources/gettext', 'sources/url_for', 'require', 'jquery',
|
||||
@@ -304,6 +309,8 @@ define('pgadmin.browser', [
|
||||
// Help menus
|
||||
help: {},
|
||||
},
|
||||
native_context_menus: {},
|
||||
|
||||
add_panels: function() {
|
||||
/* Add hooked-in panels by extensions */
|
||||
let panels = JSON.parse(pgBrowser.panels_items);
|
||||
@@ -366,6 +373,77 @@ 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;
|
||||
let category = {
|
||||
'common': []
|
||||
};
|
||||
for(let _key of Object.keys(obj.menus[name][d._type])){
|
||||
let menuCategory = obj.menus[name][d._type][_key].category;
|
||||
let menuItem = obj.menus[name][d._type][_key];
|
||||
|
||||
if(menuCategory in this.menu_categories) {
|
||||
category[menuCategory] ? category[menuCategory].push(menuItem): category[menuCategory] = [menuItem];
|
||||
} else if (!_.isUndefined(menuCategory)) {
|
||||
category[menuCategory] ? category[menuCategory].push(menuItem): category[menuCategory] = [menuItem];
|
||||
} else {
|
||||
category['common'].push(menuItem);
|
||||
}
|
||||
}
|
||||
let menuItemList = [];
|
||||
|
||||
for(let c in category) {
|
||||
|
||||
if((c in obj.menu_categories || category[c].length > 1) && c != 'common' ) {
|
||||
let is_all_option_dis = true;
|
||||
category[c].forEach((c)=> {
|
||||
c.is_disabled = c.disabled(d, item);
|
||||
if(is_all_option_dis)
|
||||
is_all_option_dis = c.is_disabled;
|
||||
});
|
||||
|
||||
let label = c in obj.menu_categories ? obj.menu_categories[c].label : c;
|
||||
let priority = c in obj.menu_categories ? obj.menu_categories[c].priority || 10 : 10;
|
||||
if(!is_all_option_dis && skipDisabled){
|
||||
let _menuItem = MainMenuItemFactory.create({
|
||||
name: c,
|
||||
label: label,
|
||||
module:c,
|
||||
category: c,
|
||||
menu_items: category[c],
|
||||
priority: priority
|
||||
});
|
||||
|
||||
menuItemList.push(_menuItem);
|
||||
} else if(!skipDisabled){
|
||||
let _menuItem = MainMenuItemFactory.create({
|
||||
name: c,
|
||||
label: label,
|
||||
module:c,
|
||||
category: c,
|
||||
menu_items: category[c],
|
||||
priority: priority
|
||||
});
|
||||
|
||||
menuItemList.push(_menuItem);
|
||||
}
|
||||
} else {
|
||||
category[c].forEach((c)=> {
|
||||
c.is_disabled = c.disabled(d, item);
|
||||
});
|
||||
|
||||
category[c].forEach((m)=> {
|
||||
if(!skipDisabled) {
|
||||
menuItemList.push(m);
|
||||
} else if(skipDisabled && !m.is_disabled){
|
||||
menuItemList.push(m);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return menuItemList;
|
||||
},
|
||||
// Enable/disable menu options
|
||||
enable_disable_menus: function(item) {
|
||||
// Mechanism to enable/disable menus depending on the condition.
|
||||
@@ -376,12 +454,13 @@ define('pgadmin.browser', [
|
||||
$obj_mnu = navbar.find('li#mnu_obj .dropdown-menu').first(),
|
||||
// data for current selected object
|
||||
d = item ? obj.tree.itemData(item) : undefined,
|
||||
update_menuitem = function(m) {
|
||||
update_menuitem = function(m, o) {
|
||||
if (m instanceof pgAdmin.Browser.MenuItem) {
|
||||
m.update(d, item);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (let key in m) {
|
||||
update_menuitem(m[key]);
|
||||
update_menuitem(m[key], o);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -396,19 +475,38 @@ define('pgadmin.browser', [
|
||||
// All menus (except for the object menus) are already present.
|
||||
// They will just require to check, wheather they are
|
||||
// enabled/disabled.
|
||||
_.each([
|
||||
{m: 'file', id: '#mnu_file'},
|
||||
{m: 'management', id: '#mnu_management'},
|
||||
{m: 'tools', id: '#mnu_tools'},
|
||||
{m: 'help', id:'#mnu_help'}], function(o) {
|
||||
_.each( obj.menus[o.m], function(m) { update_menuitem(m); });
|
||||
});
|
||||
let {name: browser} = getBrowser();
|
||||
if(browser == 'Nwjs') {
|
||||
pgBrowser.MainMenus.forEach((menu) => {
|
||||
menu.menuItems.forEach((item) => {
|
||||
item.setDisabled(item.disabled(d, item));
|
||||
});
|
||||
});
|
||||
}else {
|
||||
_.each([
|
||||
{name: 'file', id: '#mnu_file', label: gettext('File')},
|
||||
{name: 'management', id: '#mnu_management', label: gettext('Management')},
|
||||
{name: 'tools', id: '#mnu_tools', label: gettext('Tools')},
|
||||
{name: 'help', id:'#mnu_help', label: gettext('Help')}], function(o) {
|
||||
_.each( obj.menus[o.name], function(m) {
|
||||
update_menuitem(m, o);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Create the object menu dynamically
|
||||
if (item && obj.menus['object'] && obj.menus['object'][d._type]) {
|
||||
pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $obj_mnu, obj.menus['object'][d._type], obj.menu_categories, d, item
|
||||
);
|
||||
if(browser == 'Nwjs') {
|
||||
let menuItemList = obj.getMenuList('object', item, d);
|
||||
let objectMenu = pgBrowser.MainMenus.filter((menu) => menu.name == 'object');
|
||||
objectMenu.length > 0 && refreshMainMenuItems(objectMenu[0], menuItemList);
|
||||
let ctxMenuList = obj.getMenuList('context', item, d, true);
|
||||
obj.native_context_menus = getContextMenu(ctxMenuList, item, d);
|
||||
} else {
|
||||
pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $obj_mnu, obj.menus['object'][d._type], obj.menu_categories, d, item
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Create a dummy 'no object seleted' menu
|
||||
let create_submenu = pgAdmin.Browser.MenuGroup(
|
||||
@@ -465,7 +563,6 @@ define('pgadmin.browser', [
|
||||
initializeModalProvider();
|
||||
initializeNotifier();
|
||||
|
||||
|
||||
// Syntax highlight the SQL Pane
|
||||
if(document.getElementById('sql-textarea')){
|
||||
obj.editor = CodeMirror.fromTextArea(
|
||||
@@ -517,9 +614,14 @@ define('pgadmin.browser', [
|
||||
context_menu = {};
|
||||
|
||||
if(item) obj.tree.select(item);
|
||||
pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $div, menus, obj.menu_categories, d, item, context_menu
|
||||
);
|
||||
let {name: browser} = getBrowser();
|
||||
if(browser == 'Nwjs'){
|
||||
context_menu = obj.native_context_menus;
|
||||
} else {
|
||||
pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $div, menus, obj.menu_categories, d, item, context_menu
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
autoHide: false,
|
||||
@@ -677,12 +779,15 @@ define('pgadmin.browser', [
|
||||
let self = this,
|
||||
pgMenu = this.menus,
|
||||
MenuItem = pgAdmin.Browser.MenuItem;
|
||||
let {name: browser} = getBrowser();
|
||||
// MenuItem = pgAdmin.Browser.MenuItem;
|
||||
_.each(menus, function(m) {
|
||||
_.each(m.applies, function(a) {
|
||||
/* We do support menu type only from this list */
|
||||
if ($.inArray(a, [
|
||||
'context', 'file', 'edit', 'object',
|
||||
'management', 'tools', 'help']) >= 0) {
|
||||
// if ($.inArray(a, [
|
||||
// 'context', 'file', 'edit', 'object',
|
||||
// 'management', 'tools', 'help']) >= 0) {
|
||||
if(['context', 'file', 'edit', 'object','management', 'tools', 'help'].indexOf(a) > -1){
|
||||
let _menus;
|
||||
|
||||
// If current node is not visible in browser tree
|
||||
@@ -714,14 +819,55 @@ define('pgadmin.browser', [
|
||||
} else if(_.isString(_m.enable) && _m.enable.toLowerCase() == 'false') {
|
||||
enable = false;
|
||||
}
|
||||
return new MenuItem({
|
||||
name: _m.name, label: _m.label, module: _m.module,
|
||||
category: _m.category, callback: _m.callback,
|
||||
priority: _m.priority, data: _m.data, url: _m.url || '#',
|
||||
target: _m.target, icon: _m.icon,
|
||||
enable,
|
||||
node: _m.node, checked: _m.checked, below: _m.below,
|
||||
});
|
||||
|
||||
// This is to handel quick search callback
|
||||
if(gettext(_m.label) == gettext('Quick Search')) {
|
||||
_m.callback = () => {
|
||||
// Render Search component
|
||||
Notify.showModal(gettext('Quick Search'), (closeModal) => {
|
||||
return <Search closeModal={closeModal}/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: false, showFullScreen: false, isFullWidth: false, showTitle: false}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if(browser == 'Nwjs') {
|
||||
return MainMenuItemFactory.create({
|
||||
name: _m.name,
|
||||
label: _m.label,
|
||||
module: _m.module,
|
||||
category: _m.category,
|
||||
callback: typeof _m.module == 'object' && _m.module[_m.callback] && _m.callback in _m.module[_m.callback] ? _m.module[_m.callback] : _m.callback,
|
||||
priority: _m.priority,
|
||||
data: _m.data,
|
||||
url: _m.url || '#',
|
||||
target: _m.target,
|
||||
icon: _m.icon,
|
||||
enable: enable ? enable : true,
|
||||
node: _m.node,
|
||||
checked: _m.checked,
|
||||
below: _m.below,
|
||||
applies: _m.applies,
|
||||
});
|
||||
} else {
|
||||
return new MenuItem({
|
||||
name: _m.name,
|
||||
label: _m.label,
|
||||
module: _m.module,
|
||||
category: _m.category,
|
||||
callback: _m.callback,
|
||||
priority: _m.priority,
|
||||
data: _m.data,
|
||||
url: _m.url || '#',
|
||||
target: _m.target,
|
||||
icon: _m.icon,
|
||||
enable,
|
||||
node: _m.node,
|
||||
checked: _m.checked,
|
||||
below: _m.below,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!_.has(_menus, m.name)) {
|
||||
@@ -747,35 +893,41 @@ define('pgadmin.browser', [
|
||||
});
|
||||
},
|
||||
// Create the menus
|
||||
create_menus: function() {
|
||||
create_menus: function () {
|
||||
let { name: browser } = getBrowser();
|
||||
// Add Native menus if NWjs app
|
||||
if (browser == 'Nwjs') {
|
||||
createMainMenus();
|
||||
this.enable_disable_menus();
|
||||
} else {
|
||||
/* Create menus */
|
||||
let navbar = $('#navbar-menu > ul').first();
|
||||
let obj = this;
|
||||
|
||||
/* Create menus */
|
||||
let navbar = $('#navbar-menu > ul').first();
|
||||
let obj = this;
|
||||
_.each([
|
||||
{ menu: 'file', id: '#mnu_file' },
|
||||
{ menu: 'management', id: '#mnu_management' },
|
||||
{ menu: 'tools', id: '#mnu_tools' },
|
||||
{ menu: 'help', id: '#mnu_help' }],
|
||||
function (o) {
|
||||
let $mnu = navbar.children(o.id).first(),
|
||||
$dropdown = $mnu.children('.dropdown-menu').first();
|
||||
$dropdown.empty();
|
||||
if (o.menu == 'help') {
|
||||
$dropdown.append('<div id="quick-search-component"></div>');
|
||||
$dropdown.append('<div class="menu-groups"><span class="fa fa-list" style="font-weight:900 !important;"></span> ' + gettext('SUGGESTED SITES') + '</div>');
|
||||
}
|
||||
|
||||
_.each([
|
||||
{menu: 'file', id: '#mnu_file'},
|
||||
{menu: 'management', id: '#mnu_management'},
|
||||
{menu: 'tools', id: '#mnu_tools'},
|
||||
{menu: 'help', id:'#mnu_help'}],
|
||||
function(o) {
|
||||
let $mnu = navbar.children(o.id).first(),
|
||||
$dropdown = $mnu.children('.dropdown-menu').first();
|
||||
$dropdown.empty();
|
||||
if(o.menu == 'help'){
|
||||
$dropdown.append('<div id="quick-search-component"></div>');
|
||||
$dropdown.append('<div class="menu-groups"><span class="fa fa-list" style="font-weight:900 !important;"></span> ' + gettext('SUGGESTED SITES') + '</div>');
|
||||
}
|
||||
if (pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $dropdown, obj.menus[o.menu], obj.menu_categories
|
||||
)) {
|
||||
$mnu.removeClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
if (pgAdmin.Browser.MenuCreator(
|
||||
obj.Nodes, $dropdown, obj.menus[o.menu], obj.menu_categories
|
||||
)) {
|
||||
$mnu.removeClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
navbar.children('#mnu_obj').removeClass('d-none');
|
||||
obj.enable_disable_menus();
|
||||
navbar.children('#mnu_obj').removeClass('d-none');
|
||||
obj.enable_disable_menus();
|
||||
}
|
||||
},
|
||||
// General function to handle callbacks for object or dialog help.
|
||||
showHelp: function(type, url, node, item) {
|
||||
|
||||
@@ -45,7 +45,6 @@ define([
|
||||
name: 'refresh', node: this.type, module: this,
|
||||
applies: ['object', 'context'], callback: 'refresh',
|
||||
priority: 2, label: gettext('Refresh'),
|
||||
icon: 'fa fa-sync-alt',
|
||||
}]);
|
||||
|
||||
// show query tool only in context menu of supported nodes.
|
||||
@@ -55,7 +54,6 @@ define([
|
||||
name: 'show_query_tool', node: this.type, module: this,
|
||||
applies: ['context'], callback: 'show_query_tool',
|
||||
priority: 998, label: gettext('Query Tool'),
|
||||
icon: 'pg-font-icon icon-query_tool',
|
||||
}]);
|
||||
|
||||
// show search objects same as query tool
|
||||
@@ -63,7 +61,6 @@ define([
|
||||
name: 'search_objects', node: this.type, module: this,
|
||||
applies: ['context'], callback: 'show_search_objects',
|
||||
priority: 997, label: gettext('Search Objects...'),
|
||||
icon: 'fa fa-search',
|
||||
}]);
|
||||
|
||||
// show psql tool same as query tool.
|
||||
@@ -72,7 +69,6 @@ define([
|
||||
name: 'show_psql_tool', node: this.type, module: this,
|
||||
applies: ['context'], callback: 'show_psql_tool',
|
||||
priority: 998, label: gettext('PSQL Tool'),
|
||||
icon: 'fas fa-terminal',
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
74
web/pgadmin/browser/static/js/main_menu.js
Normal file
74
web/pgadmin/browser/static/js/main_menu.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import gettext from 'sources/gettext';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import { getBrowser } from '../../../static/js/utils';
|
||||
import Menu, { MenuItem } from './new_menu';
|
||||
|
||||
export let MainMenus = [
|
||||
{ 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 }
|
||||
];
|
||||
|
||||
let {name: browser} = getBrowser();
|
||||
|
||||
export default function createMainMenus() {
|
||||
pgAdmin.Browser.MainMenus = [];
|
||||
MainMenus.forEach((_menu) => {
|
||||
let menuObj = Menu.create(_menu.name, _menu.label, _menu.id, _menu.index, _menu.addSepratior);
|
||||
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.menus[_menu.name]));
|
||||
let priority = null;
|
||||
menuObj.menuItems.forEach((menuItem, index)=> {
|
||||
if(index == 0) {
|
||||
priority = menuItem.priority;
|
||||
}
|
||||
|
||||
if(priority !== menuItem.priority) {
|
||||
let separateMenuItem = new MenuItem({type: 'separator'});
|
||||
menuObj.addMenuItem(separateMenuItem, index);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function refreshMainMenuItems(menu, menuItems) {
|
||||
if(browser == 'Nwjs') {
|
||||
menu.setMenuItems(menuItems);
|
||||
pgAdmin.Browser.Events.trigger('pgadmin:nw-refresh-menu-item', menu);
|
||||
}
|
||||
}
|
||||
|
||||
// Factory to create menu items for main menu.
|
||||
export class MainMenuItemFactory {
|
||||
static create(options) {
|
||||
return new MenuItem({...options, callback: () => {
|
||||
// Some callbacks registered in 'callbacks' check and call specifiec callback function
|
||||
if (options.module && 'callbacks' in options.module && options.module.callbacks[options.callback]) {
|
||||
options.module.callbacks[options.callback].apply(options.module, [options.data, pgAdmin.Browser.tree.selected()]);
|
||||
} else if (options.module && options.module[options.callback]) {
|
||||
options.module[options.callback].apply(options.module, [options.data, pgAdmin.Browser.tree.selected()]);
|
||||
} else if (options?.callback) {
|
||||
options.callback(options);
|
||||
} else {
|
||||
if (options.url != '#') {
|
||||
window.open(options.url);
|
||||
}
|
||||
}
|
||||
}}, (menu, item)=> {
|
||||
pgAdmin.Browser.Events.trigger('pgadmin:nw-enable-disable-menu-items', menu, item);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import _ from 'lodash';
|
||||
import {MenuItem as NewMenuItem} from './new_menu';
|
||||
|
||||
define([
|
||||
'sources/pgadmin', 'jquery', 'sources/utils', 'sources/gettext',
|
||||
@@ -334,7 +335,17 @@ define([
|
||||
let group = groups[m.category || 'common'] =
|
||||
groups[m.category || 'common'] || [];
|
||||
group.push(m);
|
||||
} else {
|
||||
} else if(m instanceof NewMenuItem) {
|
||||
if (m.$el) {
|
||||
m.$el.remove();
|
||||
delete m.$el;
|
||||
}
|
||||
m.generate(this, self, this.context_menu_callback, item);
|
||||
let group = groups[m.category || 'common'] =
|
||||
groups[m.category || 'common'] || [];
|
||||
group.push(m);
|
||||
}
|
||||
else {
|
||||
for (let key in m) {
|
||||
update_menuitem(m[key]);
|
||||
}
|
||||
@@ -431,6 +442,7 @@ define([
|
||||
let d = this.$element.data('pgMenu');
|
||||
if (d.cb) {
|
||||
let cb = d.module && d.module['callbacks'] && d.module['callbacks'][d.cb] || d.module && d.module[d.cb];
|
||||
cb = cb || d.cb;
|
||||
if (cb) {
|
||||
cb.apply(d.module, [d.data, pgAdmin.Browser.tree.selected()]);
|
||||
ev.preventDefault();
|
||||
|
||||
223
web/pgadmin/browser/static/js/new_menu.js
Normal file
223
web/pgadmin/browser/static/js/new_menu.js
Normal file
@@ -0,0 +1,223 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import _ from 'lodash';
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
export default class Menu {
|
||||
constructor(name, label, id, index, addSepratior) {
|
||||
this.label = label;
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.index = index || 1;
|
||||
this.menuItems = [],
|
||||
this.addSepratior = addSepratior || false;
|
||||
}
|
||||
|
||||
static create(name, label, id, index, addSepratior) {
|
||||
let menuObj = new Menu(name, label, id, index, addSepratior);
|
||||
return menuObj;
|
||||
}
|
||||
|
||||
addMenuItem(menuItem, index=null) {
|
||||
if (menuItem instanceof MenuItem) {
|
||||
menuItem.parentMenu = this;
|
||||
if(index) {
|
||||
this.menuItems.splice(index, 0, menuItem);
|
||||
} else {
|
||||
this.menuItems.push(menuItem);
|
||||
|
||||
// Sort by alphanumeric ordered first
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
|
||||
// Sort by priority
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new Error(gettext('Invalid MenuItem instance'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
addMenuItems(menuItems) {
|
||||
menuItems.forEach((item) => {
|
||||
if (item instanceof MenuItem) {
|
||||
item.parentMenu = this;
|
||||
this.menuItems.push(item);
|
||||
} else {
|
||||
let subItems = Object.values(item);
|
||||
subItems.forEach((subItem)=> {
|
||||
if (subItem instanceof MenuItem) {
|
||||
subItem.parentMenu = this;
|
||||
this.menuItems.push(subItem);
|
||||
} else {
|
||||
throw new Error(gettext('Invalid MenuItem instance'));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Sort by alphanumeric ordered first
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
|
||||
// Sort by priority
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setMenuItems(menuItems) {
|
||||
this.menuItems = menuItems;
|
||||
// Sort by alphanumeric ordered first
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
|
||||
// Sort by priority
|
||||
this.menuItems.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
getMenuItems() {
|
||||
return this.menuItems;
|
||||
}
|
||||
|
||||
static getContextMenus(menuList, item, node) {
|
||||
// Sort by alphanumeric ordered first
|
||||
menuList.sort(function (a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
|
||||
// Sort by priority
|
||||
menuList.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
|
||||
let ctxMenus = {};
|
||||
let ctxIndex = 1;
|
||||
menuList.forEach(ctx => {
|
||||
let ctx_uid = _.uniqueId('ctx_');
|
||||
let sub_ctx_item = {};
|
||||
ctx.is_disabled = ctx.disabled(node, item);
|
||||
if ('menu_items' in ctx && ctx.menu_items) {
|
||||
ctx.menu_items.forEach((c) => {
|
||||
c.is_disabled = c.disabled(node, item);
|
||||
if (!c.is_disabled) {
|
||||
sub_ctx_item[ctx_uid + _.uniqueId('_sub_')] = c.getContextItem(c.label, c.is_disabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!ctx.is_disabled) {
|
||||
ctxMenus[ctx_uid + '_' + ctx.priority + '_' + + ctxIndex + '_itm'] = ctx.getContextItem(ctx.label, ctx.is_disabled, sub_ctx_item);
|
||||
|
||||
if (_.size(sub_ctx_item) > 0 && ['register', 'create'].includes(ctx.category)) {
|
||||
ctxMenus[ctx_uid + '_' + ctx.priority + '_' + + ctxIndex + '_sep'] = '----';
|
||||
}
|
||||
}
|
||||
ctxIndex++;
|
||||
});
|
||||
|
||||
return ctxMenus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class MenuItem {
|
||||
constructor(options, onDisableChange) {
|
||||
let menu_opts = [
|
||||
'name', 'label', 'priority', 'module', 'callback', 'data', 'enable',
|
||||
'category', 'target', 'url', 'node',
|
||||
'checked', 'below', 'menu_items', 'is_checkbox', 'action', 'applies', 'is_native_only', 'type'
|
||||
];
|
||||
let defaults = {
|
||||
url: '#',
|
||||
target: '_self',
|
||||
enable: true,
|
||||
type: 'normal'
|
||||
};
|
||||
_.extend(this, defaults, _.pick(options, menu_opts));
|
||||
if (!this.callback) {
|
||||
this.callback = (item) => {
|
||||
if (item.url != '#') {
|
||||
window.open(item.url);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.onDisableChange = onDisableChange;
|
||||
}
|
||||
|
||||
static create(options) {
|
||||
return MenuItem(options);
|
||||
}
|
||||
|
||||
contextMenuCallback(self) {
|
||||
self.callback();
|
||||
}
|
||||
|
||||
getContextItem(label, is_disabled, sub_ctx_item) {
|
||||
let self = this;
|
||||
return {
|
||||
name: label,
|
||||
disabled: is_disabled,
|
||||
callback: () => { this.contextMenuCallback(self); },
|
||||
...(sub_ctx_item && Object.keys(sub_ctx_item).length > 0) && { items: sub_ctx_item }
|
||||
};
|
||||
}
|
||||
|
||||
setDisabled(disabled) {
|
||||
this.is_disabled = disabled;
|
||||
this.onDisableChange?.(this.parentMenu, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks this menu enable/disable state based on the selection.
|
||||
*/
|
||||
disabled(node, item) {
|
||||
if (this.enable == undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.node) {
|
||||
if (!node) {
|
||||
return true;
|
||||
}
|
||||
if (_.isArray(this.node) ? (
|
||||
_.indexOf(this.node, node) == -1
|
||||
) : (this.node != node._type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_.isBoolean(this.enable)) return !this.enable;
|
||||
if (_.isFunction(this.enable)) {
|
||||
return !this.enable.apply(this.module, [node, item, this.data]);
|
||||
}
|
||||
if (this.module && _.isBoolean(this.module[this.enable])) {
|
||||
return !this.module[this.enable];
|
||||
}
|
||||
if (this.module && _.isFunction(this.module[this.enable])) {
|
||||
return !(this.module[this.enable]).apply(this.module, [node, item, this.data]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getContextMenu(menu, item, node) {
|
||||
return Menu.getContextMenus(menu, item, node);
|
||||
}
|
||||
@@ -111,7 +111,7 @@ define('pgadmin.browser.node', [
|
||||
callback: 'refresh',
|
||||
priority: 2,
|
||||
label: gettext('Refresh...'),
|
||||
icon: 'fa fa-sync-alt',
|
||||
enable: true,
|
||||
}]);
|
||||
|
||||
if (self.canEdit) {
|
||||
@@ -126,7 +126,6 @@ define('pgadmin.browser.node', [
|
||||
data: {
|
||||
'action': 'edit',
|
||||
},
|
||||
icon: 'fa fa-edit',
|
||||
enable: _.isFunction(self.canEdit) ?
|
||||
function() {
|
||||
return !!(self.canEdit.apply(self, arguments));
|
||||
@@ -147,7 +146,6 @@ define('pgadmin.browser.node', [
|
||||
'url': 'drop',
|
||||
data_disabled: gettext('The selected tree node does not support this option.'),
|
||||
},
|
||||
icon: 'fa fa-trash-alt',
|
||||
enable: _.isFunction(self.canDrop) ?
|
||||
function() {
|
||||
return !!(self.canDrop.apply(self, arguments));
|
||||
@@ -166,7 +164,6 @@ define('pgadmin.browser.node', [
|
||||
data: {
|
||||
'url': 'delete',
|
||||
},
|
||||
icon: 'fa fa-trash-alt',
|
||||
enable: _.isFunction(self.canDropCascade) ?
|
||||
function() {
|
||||
return self.canDropCascade.apply(self, arguments);
|
||||
@@ -193,7 +190,6 @@ define('pgadmin.browser.node', [
|
||||
callback: 'show_query_tool',
|
||||
priority: 998,
|
||||
label: gettext('Query Tool'),
|
||||
icon: 'pg-font-icon icon-query_tool',
|
||||
enable: enable,
|
||||
}]);
|
||||
|
||||
@@ -211,7 +207,6 @@ define('pgadmin.browser.node', [
|
||||
name: 'show_psql_tool', node: this.type, module: this,
|
||||
applies: ['context'], callback: 'show_psql_tool',
|
||||
priority: 998, label: gettext('PSQL Tool'),
|
||||
icon: 'fas fa-terminal',
|
||||
}]);
|
||||
}
|
||||
}
|
||||
@@ -240,7 +235,6 @@ define('pgadmin.browser.node', [
|
||||
'script': stype,
|
||||
data_disabled: gettext('The selected tree node does not support this option.'),
|
||||
},
|
||||
icon: 'fa fa-pencil-alt',
|
||||
enable: self.check_user_permission,
|
||||
}]);
|
||||
});
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {Search} from './quick_search/trigger_search';
|
||||
|
||||
// TODO: GUI, Add the logic to show loading screen while fetching result
|
||||
const onResultFetch = (url, data) => {
|
||||
// URL can be used for displaying all the result in new page
|
||||
// data will be array of search <name> -> <link>
|
||||
console.warn('URL = ' + url);
|
||||
console.warn(data);
|
||||
};
|
||||
|
||||
setTimeout(function(){
|
||||
if (document.getElementById('quick-search-component')) {
|
||||
ReactDOM.render(
|
||||
<Search onResult={onResultFetch} />,
|
||||
document.getElementById('quick-search-component')
|
||||
);
|
||||
}
|
||||
},500);
|
||||
@@ -6,86 +6,79 @@
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
import {MenuItem as NewMenuItem} from '../new_menu';
|
||||
import { MainMenus } from '../main_menu';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import { getBrowser } from '../../../../static/js/utils';
|
||||
|
||||
|
||||
// Allow us to
|
||||
const getMenuName = (item) => {
|
||||
let aLinks = item.getElementsByTagName('a');
|
||||
let name;
|
||||
if (aLinks.length > 0) {
|
||||
name = (aLinks[0].text).trim();
|
||||
name = name.replace(/\.+$/g, '');
|
||||
}
|
||||
return name;
|
||||
return item.label;
|
||||
};
|
||||
|
||||
export function menuSearch(param, props) {
|
||||
let LAST_MENU;
|
||||
param = param.trim();
|
||||
const setState = props.setState;
|
||||
let result = [];
|
||||
|
||||
if (window.pgAdmin.Browser.utils.app_name) {
|
||||
LAST_MENU = gettext('About '+ window.pgAdmin.Browser.utils.app_name);
|
||||
}
|
||||
|
||||
// Here we will add the matches
|
||||
const parseLI = (_menu, path) => {
|
||||
let _name = getMenuName(_menu);
|
||||
if (_name && _name.toLowerCase().indexOf(param.toLowerCase()) != -1) {
|
||||
let _res = {};
|
||||
_res[_name] = path;
|
||||
_res['element'] = _menu.children[0];
|
||||
result.push(_res);
|
||||
}
|
||||
// Check if last menu then update the parent component's state
|
||||
if (_name === LAST_MENU) {
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
data: result,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// Recursive function to search in UL
|
||||
const parseUL = (menu, path) => {
|
||||
const menus = Array.from(menu.children);
|
||||
menus.forEach((_menu) => {
|
||||
let _name, _path;
|
||||
if (_menu.tagName == 'UL') {
|
||||
_name = getMenuName(_menu);
|
||||
_path = `${path}/${_name}`;
|
||||
iterItem(_menu, _path);
|
||||
} else if (_menu.tagName == 'LI') {
|
||||
if (_menu.classList.contains('dropdown-submenu')) {
|
||||
_name = getMenuName(_menu);
|
||||
_path = `${path}/${_name}`;
|
||||
iterItem(_menu, _path);
|
||||
const iterItem = (subMenus, path, parentPath) => {
|
||||
subMenus.forEach((subMenu) =>{
|
||||
if(subMenu instanceof NewMenuItem || subMenu instanceof pgAdmin.Browser.MenuItem) {
|
||||
if(subMenu.type != 'separator' && subMenu?.label?.toLowerCase().indexOf(param.toLowerCase()) != -1){
|
||||
let localPath = path;
|
||||
if(parentPath) {
|
||||
localPath = `${parentPath} > ${path} `;
|
||||
}
|
||||
subMenu.path = localPath;
|
||||
let selectedNode = pgAdmin.Browser.tree.selected();
|
||||
if(subMenu.path == 'Object') {
|
||||
if(selectedNode && selectedNode._metadata.data._type == subMenu.module.parent_type) {
|
||||
result.push(subMenu);
|
||||
}
|
||||
} else {
|
||||
result.push(subMenu);
|
||||
}
|
||||
}
|
||||
if(subMenu.menu_items) {
|
||||
iterItem(subMenu.menu_items, getMenuName(subMenu), path);
|
||||
}
|
||||
} else {
|
||||
if(typeof(subMenu) == 'object' && !(subMenu instanceof NewMenuItem || subMenu instanceof pgAdmin.Browser.MenuItem)) {
|
||||
iterItem(Object.values(subMenu), path, parentPath);
|
||||
} else {
|
||||
parseLI(_menu, path);
|
||||
iterItem(subMenu, path, parentPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Expects LI of menus which contains A & UL
|
||||
const iterItem = (menu, path) => {
|
||||
const subMenus = Array.from(menu.children);
|
||||
subMenus.forEach((_menu) => {
|
||||
if (_menu.tagName == 'UL') {
|
||||
parseUL(_menu, path);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Starting Point
|
||||
const navbar = document.querySelector('.navbar-nav');
|
||||
const mainMenus = Array.from(navbar.children);
|
||||
let {name: browser} = getBrowser();
|
||||
const mainMenus = browser == 'Nwjs' ?pgAdmin.Browser.MainMenus : MainMenus;
|
||||
if(browser == 'Nwjs') {
|
||||
mainMenus.forEach((menu) => {
|
||||
let subMenus = menu.menuItems;
|
||||
iterItem(subMenus, getMenuName(menu));
|
||||
});
|
||||
} else {
|
||||
mainMenus.forEach((menu) => {
|
||||
let subMenus = [];
|
||||
if(menu.name == 'object') {
|
||||
let selectedNode = pgAdmin.Browser.tree.selected();
|
||||
if(selectedNode) {
|
||||
subMenus = pgAdmin.Browser.menus[menu.name][selectedNode._metadata.data._type];
|
||||
}
|
||||
} else {
|
||||
subMenus = pgAdmin.Browser.menus[menu.name];
|
||||
}
|
||||
iterItem(Object.values(subMenus), getMenuName(menu));
|
||||
});
|
||||
}
|
||||
|
||||
mainMenus.forEach((menu) => {
|
||||
iterItem(menu, getMenuName(menu));
|
||||
});
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
data: result,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -51,43 +51,47 @@ export function onlineHelpSearch(param, props) {
|
||||
let iframeHTML = content.document;
|
||||
window.pooling = setInterval(() => {
|
||||
let resultEl = iframeHTML.getElementById('search-results');
|
||||
let searchResultsH2Tags = resultEl.getElementsByTagName('h2');
|
||||
let list = resultEl && resultEl.getElementsByTagName('LI');
|
||||
let pooling = window.pooling;
|
||||
if ((list && list.length > 0 )) {
|
||||
let res = extractSearchResult(list);
|
||||
// After getting the data, we need to call the Parent component function
|
||||
// which will render the data on the screen
|
||||
if (searchResultsH2Tags[0]['childNodes'][0]['textContent'] != 'Searching') {
|
||||
window.clearInterval(pooling);
|
||||
if(resultEl) {
|
||||
let searchResultsH2Tags = resultEl.getElementsByTagName('h2');
|
||||
let list = resultEl && resultEl.getElementsByTagName('LI');
|
||||
if ((list && list.length > 0 )) {
|
||||
let res = extractSearchResult(list);
|
||||
// After getting the data, we need to call the Parent component function
|
||||
// which will render the data on the screen
|
||||
if (searchResultsH2Tags[0]['childNodes'][0]['textContent'] != 'Searching') {
|
||||
window.clearInterval(pooling);
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
clearedPooling: true,
|
||||
url: srcURL,
|
||||
data: res,
|
||||
}));
|
||||
isIFrameLoaded = false;
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById('quick-search-iframe-container'));
|
||||
} else {
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
clearedPooling: false,
|
||||
url: srcURL,
|
||||
data: res,
|
||||
}));
|
||||
}
|
||||
} else if(searchResultsH2Tags[0]['childNodes'][0]['textContent'] == 'Search Results') {
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
clearedPooling: true,
|
||||
url: srcURL,
|
||||
data: res,
|
||||
data: {},
|
||||
}));
|
||||
isIFrameLoaded = false;
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById('quick-search-iframe-container'));
|
||||
} else {
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
clearedPooling: false,
|
||||
url: srcURL,
|
||||
data: res,
|
||||
}));
|
||||
isIFrameLoaded = false;
|
||||
window.clearInterval(pooling);
|
||||
}
|
||||
} else if(searchResultsH2Tags[0]['childNodes'][0]['textContent'] == 'Search Results') {
|
||||
setState(state => ({
|
||||
...state,
|
||||
fetched: true,
|
||||
clearedPooling: true,
|
||||
url: srcURL,
|
||||
data: {},
|
||||
}));
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById('quick-search-iframe-container'));
|
||||
isIFrameLoaded = false;
|
||||
} else {
|
||||
window.clearInterval(pooling);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
@@ -7,12 +7,16 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import React, {useRef,useState, useEffect} from 'react';
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import clsx from 'clsx';
|
||||
import {useDelayDebounce} from 'sources/custom_hooks';
|
||||
import {onlineHelpSearch} from './online_help';
|
||||
import {menuSearch} from './menuitems_help';
|
||||
import $ from 'jquery';
|
||||
import gettext from 'sources/gettext';
|
||||
import PropTypes from 'prop-types';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import { getBrowser } from '../../../../static/js/utils';
|
||||
|
||||
function HelpArticleContents({isHelpLoading, isMenuLoading, helpSearchResult}) {
|
||||
return (isHelpLoading && !(isMenuLoading??true)) ? (
|
||||
@@ -39,8 +43,17 @@ HelpArticleContents.propTypes = {
|
||||
isMenuLoading: PropTypes.bool
|
||||
};
|
||||
|
||||
export function Search() {
|
||||
const useModalStyles = makeStyles(() => ({
|
||||
setTop: {
|
||||
marginTop: '-20px',
|
||||
}
|
||||
}));
|
||||
|
||||
export function Search({closeModal}) {
|
||||
let {name: browser} = getBrowser();
|
||||
const classes = useModalStyles();
|
||||
const wrapperRef = useRef(null);
|
||||
const firstEleRef = useRef();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [isShowMinLengthMsg, setIsShowMinLengthMsg] = useState(false);
|
||||
const [isMenuLoading, setIsMenuLoading] = useState(false);
|
||||
@@ -64,6 +77,7 @@ export function Search() {
|
||||
fetched: false,
|
||||
data: [],
|
||||
}));
|
||||
|
||||
setHelpSearchResult(state => ({
|
||||
...state,
|
||||
fetched: false,
|
||||
@@ -120,37 +134,37 @@ export function Search() {
|
||||
const refactorMenuItems = (items) => {
|
||||
if(items.length > 0){
|
||||
let menuItemsHtmlElement = [];
|
||||
for(let i=0; i < items.length; i++){
|
||||
Object.keys(items[i]).forEach( (value) => {
|
||||
if(value != 'element' && value != 'No object selected'){
|
||||
menuItemsHtmlElement.push( <li key={ 'li-menu-' + i }><a tabIndex='0' id={ 'li-menu-' + i } href={'#'} className={ (items[i]['element'].classList.contains('disabled') ? 'dropdown-item menu-groups-a disabled':'dropdown-item menu-groups-a')} key={ 'menu-' + i } onClick={() => {items[i]['element'].click(); toggleDropdownMenu();}}>
|
||||
{value}
|
||||
<span key={ 'menu-span-' + i }>{refactorPathToMenu(items[i][value])}</span>
|
||||
</a>
|
||||
{ ((items[i]['element'].classList.contains('disabled') && items[i]['element'].getAttribute('data-disabled') != undefined) ? <i className='fa fa-info-circle quick-search-tooltip' data-toggle='tooltip' title={items[i]['element'].getAttribute('data-disabled')} aria-label='Test data tooltip' aria-hidden='true'></i> : '' )}
|
||||
</li>);
|
||||
}
|
||||
});
|
||||
}
|
||||
items.forEach((i) => {
|
||||
menuItemsHtmlElement.push(
|
||||
<li key={ 'li-menu-' + i }><a tabIndex='0' id={ 'li-menu-' + i.label } href={'#'} className={ (i.is_disabled ? 'dropdown-item menu-groups-a disabled':'dropdown-item menu-groups-a')} key={ 'menu-' + i.label } onClick={
|
||||
() => {
|
||||
closeModal();
|
||||
if(browser == 'Nwjs') {
|
||||
i.callback();
|
||||
} else {
|
||||
// Some callbacks registered in 'callbacks' check and call specifiec callback function
|
||||
if (i.module && 'callbacks' in i.module && i.module.callbacks[i.callback]) {
|
||||
i.module.callbacks[i.callback].apply(i.module, [i.data, pgAdmin.Browser.tree.selected()]);
|
||||
} else if (i.module && i.module[i.callback]) {
|
||||
i.module[i.callback].apply(i.module, [i.data, pgAdmin.Browser.tree.selected()]);
|
||||
} else if (i.callback) {
|
||||
i.callback(i);
|
||||
} else {
|
||||
window.open(i.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}>
|
||||
{i.label}
|
||||
<span key={ 'menu-span-' + i.label }>{i.path}</span>
|
||||
</a>
|
||||
</li>);
|
||||
});
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
return menuItemsHtmlElement;
|
||||
}
|
||||
};
|
||||
|
||||
const refactorPathToMenu = (path) => {
|
||||
if(path){
|
||||
let pathArray = path.split('/');
|
||||
let spanElement = [];
|
||||
for(let i = 0; i < pathArray.length; i++ ){
|
||||
if(i == (pathArray.length -1)){
|
||||
spanElement.push(pathArray[i]);
|
||||
}else{
|
||||
spanElement.push(<span key={ 'menu-span-sub' + i }> {pathArray[i]} <i className='fa fa-angle-right' aria-hidden='true'></i> </span>);
|
||||
}
|
||||
}
|
||||
return spanElement;
|
||||
}
|
||||
};
|
||||
|
||||
const onInputValueChange = (value) => {
|
||||
let pooling = window.pooling;
|
||||
@@ -210,13 +224,19 @@ export function Search() {
|
||||
return loading ? <div className='pad-12'><div className="search-icon">{gettext('Searching...')}</div></div> : '';
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
firstEleRef.current && firstEleRef.current.focus();
|
||||
}, 350);
|
||||
}, [firstEleRef.current]);
|
||||
|
||||
return (
|
||||
<div id='quick-search-container' onClick={setSearchTerm}></div>,
|
||||
<ul id='quick-search-container' ref={wrapperRef} className='test' role="menu">
|
||||
<ul id='quick-search-container' ref={wrapperRef} className={clsx('test', classes.setTop)} role="menu">
|
||||
<li>
|
||||
<ul id='myDropdown'>
|
||||
<li className='dropdown-item-input'>
|
||||
<input tabIndex='0' autoFocus type='text' autoComplete='off' className='form-control live-search-field'
|
||||
<input ref={firstEleRef} tabIndex='0' autoFocus type='text' autoComplete='off' className='form-control live-search-field'
|
||||
aria-label='live-search-field' id='live-search-field' placeholder={gettext('Quick Search')} onChange={(e) => {onInputValueChange(e.target.value);} } />
|
||||
</li>
|
||||
<div style={{marginBottom:0}}>
|
||||
@@ -229,7 +249,6 @@ export function Search() {
|
||||
</div>)
|
||||
:''}
|
||||
<div >
|
||||
|
||||
{ (menuSearchResult.fetched && !(isMenuLoading??true) ) ?
|
||||
<div>
|
||||
<div className='menu-groups'>
|
||||
@@ -269,3 +288,8 @@ export function Search() {
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Search.propTypes = {
|
||||
closeModal: PropTypes.func
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user