diff --git a/web/pgadmin/preferences/__init__.py b/web/pgadmin/preferences/__init__.py
index 77365a4d4..c5035a465 100644
--- a/web/pgadmin/preferences/__init__.py
+++ b/web/pgadmin/preferences/__init__.py
@@ -134,6 +134,7 @@ def _iterate_categories(pref_d, label, res):
"open": True,
"children": [],
"value": gettext(pref_d['label']),
+ "name": pref_d['name']
}
for c in pref_d['categories']:
diff --git a/web/pgadmin/preferences/static/js/components/PreferencesComponent.jsx b/web/pgadmin/preferences/static/js/components/PreferencesComponent.jsx
index 435cda740..b60a47441 100644
--- a/web/pgadmin/preferences/static/js/components/PreferencesComponent.jsx
+++ b/web/pgadmin/preferences/static/js/components/PreferencesComponent.jsx
@@ -185,7 +185,7 @@ export default function PreferencesComponent({ ...props }) {
'id': id.toString(),
'label': node.label,
'_label': node.label,
- 'name': node.label,
+ 'name': node.name,
'icon': '',
'inode': true,
'type': 2,
@@ -378,7 +378,7 @@ export default function PreferencesComponent({ ...props }) {
if(field.visible && _.isNull(firstElement)) {
firstElement = field;
}
- field.tooltip = item._parent._metadata.data.name.toLowerCase() + ':' + item._metadata.data.name + ':' + field.name;
+ field.labelTooltip = item._parent._metadata.data.name.toLowerCase() + ':' + item._metadata.data.name + ':' + field.name;
});
setLoadTree(crypto.getRandomValues(new Uint16Array(1)));
initTreeTimeout = setTimeout(() => {
diff --git a/web/pgadmin/static/js/SchemaView/FormView.jsx b/web/pgadmin/static/js/SchemaView/FormView.jsx
index f454f3c51..5aa5c12ae 100644
--- a/web/pgadmin/static/js/SchemaView/FormView.jsx
+++ b/web/pgadmin/static/js/SchemaView/FormView.jsx
@@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import React, { useContext, useEffect, useRef, useState } from 'react';
-import { Box, makeStyles, Tab, Tabs, Tooltip } from '@material-ui/core';
+import { Box, makeStyles, Tab, Tabs } from '@material-ui/core';
import _ from 'lodash';
import PropTypes from 'prop-types';
import clsx from 'clsx';
@@ -363,10 +363,6 @@ export default function FormView({
]}
/>;
- if(field.tooltip) {
- currentControl = {currentControl};
- }
-
if(field.isFullTab && field.helpMessage) {
currentControl = (
diff --git a/web/pgadmin/static/js/SchemaView/MappedControl.jsx b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
index bcb1eb2a5..127456d13 100644
--- a/web/pgadmin/static/js/SchemaView/MappedControl.jsx
+++ b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
@@ -212,7 +212,7 @@ const ALLOWED_PROPS_FIELD_COMMON = [
'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName', 'hidden',
- 'withContainer', 'controlGridBasis', 'hasCheckbox', 'treeData', 'title'
+ 'withContainer', 'controlGridBasis', 'hasCheckbox', 'treeData', 'labelTooltip'
];
const ALLOWED_PROPS_FIELD_FORM = [
diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx
index eb5d83761..9889a4e81 100644
--- a/web/pgadmin/static/js/components/FormComponents.jsx
+++ b/web/pgadmin/static/js/components/FormComponents.jsx
@@ -12,7 +12,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState }
import { makeStyles } from '@material-ui/core/styles';
import {
Box, FormControl, OutlinedInput, FormHelperText,
- Grid, IconButton, FormControlLabel, Switch, Checkbox, useTheme, InputLabel, Paper, Select as MuiSelect, Radio,
+ Grid, IconButton, FormControlLabel, Switch, Checkbox, useTheme, InputLabel, Paper, Select as MuiSelect, Radio, Tooltip,
} from '@material-ui/core';
import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab';
import ErrorRoundedIcon from '@material-ui/icons/ErrorOutlineRounded';
@@ -127,7 +127,7 @@ FormIcon.propTypes = {
};
/* Wrapper on any form component to add label, error indicator and help message */
-export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9 }) {
+export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9, labelTooltip='' }) {
const classes = useStyles();
const cid = testcid || _.uniqueId('c');
const helpid = `h${cid}`;
@@ -149,13 +149,20 @@ export function FormInput({ children, error, className, label, helpMessage, requ
>
);
}
+
+ let labelComponent =
+ {label}
+
+ ;
return (
-
- {label}
-
-
+ {
+ labelTooltip ?
+
+ {labelComponent}
+ : labelComponent
+ }
@@ -178,6 +185,7 @@ FormInput.propTypes = {
withContainer: PropTypes.bool,
labelGridBasis: PropTypes.number,
controlGridBasis: PropTypes.number,
+ labelTooltip: PropTypes.string
};
export function InputSQL({ value, options, onChange, className, controlProps, inputRef, ...props }) {
@@ -325,9 +333,9 @@ InputDateTimePicker.propTypes = {
controlProps: PropTypes.object,
};
-export function FormInputDateTimePicker({ hasError, required, label, className, helpMessage, testcid, ...props }) {
+export function FormInputDateTimePicker({ hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -342,6 +350,7 @@ FormInputDateTimePicker.propTypes = {
value: PropTypes.string,
controlProps: PropTypes.object,
change: PropTypes.func,
+ labelTooltip: PropTypes.string
};
/* Use forwardRef to pass ref prop to OutlinedInput */
@@ -426,9 +435,9 @@ InputText.propTypes = {
inputStyle: PropTypes.object
};
-export function FormInputText({ hasError, required, label, className, helpMessage, testcid, ...props }) {
+export function FormInputText({ hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -440,6 +449,7 @@ FormInputText.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
+ labelTooltip: PropTypes.string
};
export function InputFileSelect({ controlProps, onChange, disabled, readonly, isvalidate = false, hideBrowseButton=false,validate, ...props }) {
@@ -488,10 +498,10 @@ InputFileSelect.propTypes = {
};
export function FormInputFileSelect({
- hasError, required, label, className, helpMessage, testcid, ...props }) {
+ hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -503,6 +513,7 @@ FormInputFileSelect.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
+ labelTooltip: PropTypes.string
};
export function InputSwitch({ cid, helpid, value, onChange, readonly, controlProps, ...props }) {
@@ -533,10 +544,10 @@ InputSwitch.propTypes = {
controlProps: PropTypes.object,
};
-export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, withContainer, controlGridBasis, ...props }) {
+export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, withContainer, controlGridBasis, labelTooltip, ...props }) {
return (
+ helpMessage={helpMessage} testcid={testcid} withContainer={withContainer} controlGridBasis={controlGridBasis} labelTooltip={labelTooltip}>
);
@@ -550,6 +561,7 @@ FormInputSwitch.propTypes = {
testcid: PropTypes.string,
withContainer: PropTypes.bool,
controlGridBasis: PropTypes.number,
+ labelTooltip: PropTypes.string
};
export function InputCheckbox({ cid, helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) {
@@ -581,10 +593,10 @@ InputCheckbox.propTypes = {
};
export function FormInputCheckbox({ hasError, required, label,
- className, helpMessage, testcid, ...props }) {
+ className, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -596,6 +608,7 @@ FormInputCheckbox.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
+ labelTooltip: PropTypes.string
};
export function InputRadio({ helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) {
@@ -675,9 +688,9 @@ InputToggle.propTypes = {
};
export function FormInputToggle({ hasError, required, label,
- className, helpMessage, testcid, inputRef, ...props }) {
+ className, helpMessage, testcid, inputRef, labelTooltip, ...props }) {
return (
-
+
);
@@ -689,7 +702,8 @@ FormInputToggle.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
- inputRef: CustomPropTypes.ref
+ inputRef: CustomPropTypes.ref,
+ labelTooltip: PropTypes.string
};
/* react-select package is used for select input
@@ -1022,9 +1036,9 @@ InputSelect.propTypes = {
export function FormInputSelect({
- hasError, required, className, label, helpMessage, testcid, ...props }) {
+ hasError, required, className, label, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -1036,7 +1050,8 @@ FormInputSelect.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
- inputRef: CustomPropTypes.ref
+ inputRef: CustomPropTypes.ref,
+ labelTooltip: PropTypes.string
};
const ColorButton = withColorPicker(PgIconButton);
@@ -1062,10 +1077,10 @@ InputColor.propTypes = {
};
export function FormInputColor({
- hasError, required, className, label, helpMessage, testcid, ...props }) {
+ hasError, required, className, label, helpMessage, testcid, labelTooltip, ...props }) {
return (
-
+
);
@@ -1076,7 +1091,8 @@ FormInputColor.propTypes = {
className: CustomPropTypes.className,
label: PropTypes.string,
helpMessage: PropTypes.string,
- testcid: PropTypes.string
+ testcid: PropTypes.string,
+ labelTooltip: PropTypes.string
};
export function PlainString({ controlProps, value }) {
@@ -1193,10 +1209,10 @@ const useStylesKeyboardShortcut = makeStyles(() => ({
}
}));
-export function FormInputKeyboardShortcut({ hasError, label, className, helpMessage, onChange, ...props }) {
+export function FormInputKeyboardShortcut({ hasError, label, className, helpMessage, onChange, labelTooltip, ...props }) {
const classes = useStylesKeyboardShortcut();
return (
-
+
@@ -1208,14 +1224,15 @@ FormInputKeyboardShortcut.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ labelTooltip: PropTypes.string
};
-export function FormInputQueryThreshold({ hasError, label, className, helpMessage, testcid, onChange, ...props }) {
+export function FormInputQueryThreshold({ hasError, label, className, helpMessage, testcid, onChange, labelTooltip, ...props }) {
const cid = _.uniqueId('c');
const helpid = `h${cid}`;
return (
-
+
@@ -1227,15 +1244,16 @@ FormInputQueryThreshold.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ labelTooltip: PropTypes.string
};
-export function FormInputSelectThemes({ hasError, label, className, helpMessage, testcid, onChange, ...props }) {
+export function FormInputSelectThemes({ hasError, label, className, helpMessage, testcid, onChange, labelTooltip, ...props }) {
const cid = _.uniqueId('c');
const helpid = `h${cid}`;
return (
-
+
);
@@ -1247,7 +1265,8 @@ FormInputSelectThemes.propTypes = {
className: CustomPropTypes.className,
helpMessage: PropTypes.string,
testcid: PropTypes.string,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ labelTooltip: PropTypes.string
};
diff --git a/web/pgadmin/static/js/components/KeyboardShortcuts.jsx b/web/pgadmin/static/js/components/KeyboardShortcuts.jsx
index daee13320..d158a09e1 100644
--- a/web/pgadmin/static/js/components/KeyboardShortcuts.jsx
+++ b/web/pgadmin/static/js/components/KeyboardShortcuts.jsx
@@ -27,7 +27,7 @@ const useStyles = makeStyles((theme) => ({
}
}));
-export default function KeyboardShortcuts({ value, onChange, fields, title }) {
+export default function KeyboardShortcuts({ value, onChange, fields }) {
const classes = useStyles();
const keyCid = _.uniqueId('c');
const keyhelpid = `h${keyCid}`;
@@ -91,7 +91,7 @@ export default function KeyboardShortcuts({ value, onChange, fields, title }) {
{
onKeyDown: onKeyDown,
}
- } title={title} />
+ }/>
;
} else if (element.name == 'shift') {
@@ -128,6 +128,5 @@ export default function KeyboardShortcuts({ value, onChange, fields, title }) {
KeyboardShortcuts.propTypes = {
value: PropTypes.object,
onChange: PropTypes.func,
- fields: PropTypes.array,
- title: PropTypes.string
+ fields: PropTypes.array
};
diff --git a/web/setup.py b/web/setup.py
index 7cf7f02a8..412d674e3 100644
--- a/web/setup.py
+++ b/web/setup.py
@@ -17,6 +17,7 @@ from rich.console import Console
from rich.table import Table
from rich import box, print
import json as jsonlib
+from functools import wraps
console = Console()
app = typer.Typer()
@@ -54,9 +55,26 @@ from flask_babel import gettext
app = typer.Typer(pretty_exceptions_show_locals=False)
+def update_sqlite_path(f):
+ """
+ This function will behave as a decorator which will check if
+ sqlite path is provided and will update it in config
+ """
+
+ @wraps(f)
+ def wrap(*args, **kwargs):
+ if kwargs and kwargs.get('sqlite_path') is not None:
+ # update the sqlite path
+ config.SQLITE_PATH = kwargs['sqlite_path']
+ return f(*args, **kwargs)
+
+ return wrap
+
+
class ManageServers:
@app.command()
+ @update_sqlite_path
def dump_servers(output_file: str, user: Optional[str] = None,
auth_source: Optional[str] = INTERNAL,
sqlite_path: Optional[str] = None,
@@ -66,10 +84,6 @@ class ManageServers:
# What user?
dump_user = user if user is not None else config.DESKTOP_USER
- # And the sqlite path
- if sqlite_path is not None:
- config.SQLITE_PATH = sqlite_path
-
print('----------')
print('Dumping servers with:')
print('User:', dump_user)
@@ -85,6 +99,7 @@ class ManageServers:
print(str(e))
@app.command()
+ @update_sqlite_path
def load_servers(input_file: str, user: Optional[str] = None,
auth_source: Optional[str] = INTERNAL,
sqlite_path: Optional[str] = None,
@@ -96,10 +111,6 @@ class ManageServers:
# What user?
load_user = user if user is not None else config.DESKTOP_USER
- # And the sqlite path
- if sqlite_path is not None:
- config.SQLITE_PATH = sqlite_path
-
print('----------')
print('Loading servers with:')
print('User:', load_user)
@@ -136,13 +147,15 @@ class AuthType(str, Enum):
class ManageUsers:
@app.command()
+ @update_sqlite_path
def add_user(email: str, password: str,
role: Annotated[Optional[bool], typer.Option(
"--admin/--nonadmin")] = False,
active: Annotated[Optional[bool],
typer.Option("--active/--inactive")] = True,
console: Optional[bool] = True,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
):
"""Add Internal user. """
@@ -157,6 +170,7 @@ class ManageUsers:
ManageUsers.create_user(data, console, json)
@app.command()
+ @update_sqlite_path
def add_external_user(username: str,
auth_source: AuthExtTypes = AuthExtTypes.oauth2,
email: Optional[str] = None,
@@ -167,7 +181,8 @@ class ManageUsers:
typer.Option(
"--active/--inactive")] = True,
console: Optional[bool] = True,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
):
"""Add external user, other than Internal like
Ldap, Ouath2, Kerberos, Webserver. """
@@ -182,14 +197,18 @@ class ManageUsers:
ManageUsers.create_user(data, console, json)
@app.command()
+ @update_sqlite_path
def delete_user(username: str,
auth_source: AuthType = AuthType.internal,
auto_confirm: Annotated[Optional[bool],
typer.Option(
- "--yes")] = False
+ "--yes")] = False,
+ sqlite_path: Optional[str] = None,
):
"""Delete the user. """
+
confirm_msg = "Are you sure you want to delete it?"
+
if auto_confirm or typer.confirm(confirm_msg):
app = create_app(config.APP_NAME + '-cli')
with app.test_request_context():
@@ -205,6 +224,7 @@ class ManageUsers:
print('Something went wrong. ' + str(msg))
@app.command()
+ @update_sqlite_path
def update_user(email: str,
password: Optional[str] = None,
role: Annotated[Optional[bool],
@@ -214,7 +234,8 @@ class ManageUsers:
typer.Option("--active/--inactive"
)] = None,
console: Optional[bool] = True,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
):
"""Update internal user."""
@@ -247,19 +268,22 @@ class ManageUsers:
print('Something went wrong. ' + str(msg))
@app.command()
+ @update_sqlite_path
def get_users(username: Optional[str] = None,
auth_source: AuthType = None,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
):
+
ManageUsers.get_users_from_db(username, auth_source, True, json)
- @app.command()
def get_users_from_db(username: Optional[str] = None,
auth_source: AuthType = None,
console: Optional[bool] = True,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
):
"""Get user(s) details."""
+
app = create_app(config.APP_NAME + '-cli')
with app.test_request_context():
if username and auth_source:
@@ -288,6 +312,7 @@ class ManageUsers:
return users_data
@app.command()
+ @update_sqlite_path
def update_external_user(username: str,
auth_source: AuthExtTypes = AuthExtTypes.oauth2,
email: Optional[str] = None,
@@ -298,7 +323,8 @@ class ManageUsers:
Optional[bool],
typer.Option("--active/--inactive")] = None,
console: Optional[bool] = True,
- json: Optional[bool] = False
+ json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
):
"""Update external users other than Internal like
Ldap, Ouath2, Kerberos, Webserver."""
@@ -320,9 +346,11 @@ class ManageUsers:
else:
status, msg = update_user(uid, data)
if status:
- _user = ManageUsers.get_users(username=username,
- auth_source=auth_source,
- console=False)
+ _user = ManageUsers.get_users_from_db(
+ username=username,
+ auth_source=auth_source,
+ console=False
+ )
ManageUsers.display_user(_user[0], console, json)
else:
print('Something went wrong. ' + str(msg))
@@ -399,7 +427,11 @@ class ManagePreferences:
return usr.id
@app.command()
- def get_prefs(json: Optional[bool] = False):
+ @update_sqlite_path
+ def get_prefs(json: Optional[bool] = False,
+ sqlite_path: Optional[str] = None,
+ ):
+
return ManagePreferences.fetch_prefs()
def fetch_prefs(id: Optional[bool] = None, json: Optional[bool] = False):
@@ -447,13 +479,16 @@ class ManagePreferences:
print(table)
@app.command()
+ @update_sqlite_path
def set_prefs(username,
pref_options: Annotated[Optional[List[str]],
typer.Argument()] = None,
auth_source: AuthType = AuthType.internal,
console: Optional[bool] = True,
json: Optional[bool] = False,
- input_file: Optional[str] = None):
+ input_file: Optional[str] = None,
+ sqlite_path: Optional[str] = None,
+ ):
"""Set User preferences."""
if input_file:
@@ -593,5 +628,9 @@ def setup_db(app: Annotated[str, typer.Argument(
run_migration_for_sqlite()
-if __name__ == "__main__":
+def main():
app()
+
+
+if __name__ == "__main__":
+ main()