diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js
index 8910fa844..c18378069 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js
@@ -349,7 +349,7 @@ export default class ColumnSchema extends BaseUISchema {
},{
id: 'attstorage', label: gettext('Storage'), group: gettext('Definition'),
type: 'select', mode: ['properties', 'edit'],
- cell: 'select', disabled: obj.inSchemaWithColumnCheck, first_empty: true,
+ cell: 'select', disabled: obj.inSchemaWithColumnCheck,
controlProps: { placeholder: gettext('Select storage'),
allowClear: false,
},
diff --git a/web/pgadmin/static/js/SchemaView/FormView.jsx b/web/pgadmin/static/js/SchemaView/FormView.jsx
index 645a3c12b..52d780e0f 100644
--- a/web/pgadmin/static/js/SchemaView/FormView.jsx
+++ b/web/pgadmin/static/js/SchemaView/FormView.jsx
@@ -31,7 +31,7 @@ const useStyles = makeStyles((theme)=>({
height: '100%'
},
controlRow: {
- paddingBottom: theme.spacing(1),
+ marginBottom: theme.spacing(1),
},
nestedTabPanel: {
backgroundColor: theme.otherVars.headerBg,
@@ -62,7 +62,6 @@ function SQLTab({active, getSQLValue}) {
options={{
readOnly: true,
}}
- isAsync={true}
readonly={true}
/>;
}
@@ -314,7 +313,7 @@ export default function FormView({
sqlTabActive = (Object.keys(tabs).length === tabValue);
/* Re-render and fetch the SQL tab when it is active */
tabs[sqlTabName] = [
- useMemo(()=>, [sqlTabActive]),
+ useMemo(()=>, [sqlTabActive, value]),
];
tabsClassname[sqlTabName] = classes.fullSpace;
fullTabs.push(sqlTabName);
diff --git a/web/pgadmin/static/js/SchemaView/MappedControl.jsx b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
index beea73c4a..340c2bbcb 100644
--- a/web/pgadmin/static/js/SchemaView/MappedControl.jsx
+++ b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
@@ -30,8 +30,8 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
onChange && onChange(value);
}, []);
- const onSqlChange = useCallback((e, cm) => {
- onChange && onChange(cm.getValue());
+ const onSqlChange = useCallback((value) => {
+ onChange && onChange(value);
}, []);
const onIntChange = useCallback((e) => {
diff --git a/web/pgadmin/static/js/SchemaView/index.jsx b/web/pgadmin/static/js/SchemaView/index.jsx
index 3677b31de..10a262e94 100644
--- a/web/pgadmin/static/js/SchemaView/index.jsx
+++ b/web/pgadmin/static/js/SchemaView/index.jsx
@@ -711,7 +711,7 @@ const usePropsStyles = makeStyles((theme)=>({
flexDirection: 'column'
},
controlRow: {
- paddingBottom: theme.spacing(1),
+ marginBottom: theme.spacing(1),
},
form: {
padding: theme.spacing(1),
@@ -726,6 +726,9 @@ const usePropsStyles = makeStyles((theme)=>({
buttonMargin: {
marginRight: '0.5rem',
},
+ noPadding: {
+ padding: 0,
+ }
}));
/* If its the properties tab */
@@ -757,7 +760,7 @@ function SchemaPropertiesView({
group = group || defaultTab;
if(field.isFullTab) {
- tabsClassname[group] = classes.fullSpace;
+ tabsClassname[group] = classes.noPadding;
fullTabs.push(group);
}
@@ -814,7 +817,7 @@ function SchemaPropertiesView({
readonly={readonly}
disabled={disabled}
visible={visible}
- className={classes.controlRow}
+ className={field.isFullTab ? null : classes.controlRow}
noLabel={field.isFullTab}
/>
);
@@ -846,7 +849,7 @@ function SchemaPropertiesView({
>
{tabName}
-
+
{finalTabs[tabName]}
diff --git a/web/pgadmin/static/js/components/CodeMirror.jsx b/web/pgadmin/static/js/components/CodeMirror.jsx
index 4745fda9f..350a98135 100644
--- a/web/pgadmin/static/js/components/CodeMirror.jsx
+++ b/web/pgadmin/static/js/components/CodeMirror.jsx
@@ -7,71 +7,64 @@
//
//////////////////////////////////////////////////////////////
-import React, { useEffect, useRef } from 'react';
+import React, { useEffect, useMemo, useRef } from 'react';
import {default as OrigCodeMirror} from 'bundled_codemirror';
import {useOnScreen} from 'sources/custom_hooks';
import PropTypes from 'prop-types';
+import CustomPropTypes from '../custom_prop_types';
/* React wrapper for CodeMirror */
-export default function CodeMirror({currObj, name, value, options, events, ...props}) {
+export default function CodeMirror({currEditor, name, value, options, events, className}) {
const taRef = useRef();
- const cmObj = useRef();
+ const editor = useRef();
const cmWrapper = useRef();
const isVisibleTrack = useRef();
useEffect(()=>{
/* Create the object only once on mount */
- cmObj.current = new OrigCodeMirror.fromTextArea(
+ editor.current = new OrigCodeMirror.fromTextArea(
taRef.current, options);
- currObj && currObj(cmObj.current);
-
- if(cmObj.current) {
+ editor.current.setValue(value);
+ currEditor && currEditor(editor.current);
+ if(editor.current) {
try {
- cmWrapper.current = cmObj.current.getWrapperElement();
+ cmWrapper.current = editor.current.getWrapperElement();
} catch(e) {
cmWrapper.current = null;
}
}
Object.keys(events||{}).forEach((eventName)=>{
- cmObj.current.on(eventName, events[eventName]);
+ editor.current.on(eventName, events[eventName]);
});
}, []);
- useEffect(()=>{
- /* Refresh when value changes async */
- if(props.isAsync) {
- if(cmObj.current) {
- cmObj.current.setValue(value);
- cmObj.current.refresh();
- }
+ useMemo(() => {
+ if(editor.current) {
+ editor.current.setValue(value);
}
}, [value]);
const onScreenVisible = useOnScreen(cmWrapper);
if(!isVisibleTrack.current && onScreenVisible) {
isVisibleTrack.current = true;
-
- /* Refresh when value changes */
- if(cmObj.current) {
- cmObj.current.setValue(value);
- cmObj.current.refresh();
- }
- cmObj.current.refresh();
+ editor.current?.refresh();
} else if(!onScreenVisible) {
isVisibleTrack.current = false;
}
- return ;
+ return (
+
+ );
}
CodeMirror.propTypes = {
- currObj: PropTypes.func,
+ currEditor: PropTypes.func,
name: PropTypes.string,
value: PropTypes.string,
options: PropTypes.object,
change: PropTypes.func,
events: PropTypes.object,
- isAsync: PropTypes.bool
+ className: CustomPropTypes.className,
};
diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx
index d7399cbe4..f7d146a49 100644
--- a/web/pgadmin/static/js/components/FormComponents.jsx
+++ b/web/pgadmin/static/js/components/FormComponents.jsx
@@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
/* Common form components used in pgAdmin */
-import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
+import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Box, FormControl, OutlinedInput, FormHelperText,
Grid, IconButton, FormControlLabel, Switch, Checkbox, useTheme, InputLabel, Paper } from '@material-ui/core';
@@ -59,7 +59,8 @@ const useStyles = makeStyles((theme) => ({
color: theme.palette.error.main,
},
sql: {
- height: '100%',
+ border: '1px solid ' + theme.otherVars.inputBorderColor,
+ borderRadius: theme.shape.borderRadius,
},
optionIcon: {
...theme.mixins.nodeIcon,
@@ -139,17 +140,17 @@ FormInput.propTypes = {
export function InputSQL({value, options, onChange, readonly, ...props}) {
const classes = useStyles();
- const cmObj = useRef();
+ const editor = useRef();
useEffect(()=>{
- if(cmObj.current) {
- cmObj.current.setOption('readOnly', readonly);
+ if(editor.current) {
+ editor.current.setOption('readOnly', readonly);
}
}, [readonly]);
- return (
+ return useMemo(()=>(
cmObj.current=obj}
+ currEditor={(obj)=>editor.current=obj}
value={value||''}
options={{
lineNumbers: true,
@@ -159,12 +160,12 @@ export function InputSQL({value, options, onChange, readonly, ...props}) {
className={classes.sql}
events={{
change: (cm)=>{
- onChange && onChange(cm.getValue(), cm);
+ onChange && onChange(cm.getValue());
},
}}
{...props}
/>
- );
+ ), [value]);
}
InputSQL.propTypes = {
value: PropTypes.string,
@@ -581,18 +582,23 @@ const customReactSelectStyles = (theme, readonly)=>({
color: theme.palette.text.primary,
boxShadow: 'none',
border: '1px solid ' + theme.otherVars.inputBorderColor,
+ marginTop: '2px',
}),
menuPortal: (provided)=>({
...provided, zIndex: 9999,
backgroundColor: 'inherit',
color: 'inherit',
}),
- option: (provided, state)=>({
- ...provided,
- padding: '0.5rem',
- backgroundColor: state.isFocused ? theme.palette.grey[200] :
- (state.isSelected ? theme.palette.primary.main : 'inherit'),
- }),
+ option: (provided, state)=>{
+ return {
+ ...provided,
+ padding: '0.5rem',
+ color: 'inherit',
+ backgroundColor: state.isFocused ?
+ theme.palette.grey[400] : (state.isSelected ?
+ theme.palette.primary.light : 'inherit'),
+ };
+ },
multiValue: (provided)=>({
...provided,
backgroundColor: theme.palette.grey[400],
@@ -736,11 +742,12 @@ export function InputSelect({
openMenuOnClick: !readonly,
onChange: onChangeOption,
isLoading: isLoading,
- options: controlProps.allowSelectAll ? [{ label: 'Select All', value: '*' }, ...filteredOptions] : filteredOptions,
+ options: controlProps.allowSelectAll ? [{ label: gettext('Select All'), value: '*' }, ...filteredOptions] : filteredOptions,
value: realValue,
menuPortalTarget: document.body,
styles: styles,
inputId: cid,
+ placeholder: controlProps.placeholder || gettext('Select...'),
...otherProps,
...props
};
diff --git a/web/pgadmin/static/js/custom_hooks.js b/web/pgadmin/static/js/custom_hooks.js
index 488f87bd7..4eb28d4c0 100644
--- a/web/pgadmin/static/js/custom_hooks.js
+++ b/web/pgadmin/static/js/custom_hooks.js
@@ -47,7 +47,7 @@ export function useOnScreen(ref) {
}
);
useEffect(() => {
- if (ref.current) {
+ if(ref?.current) {
observer.observe(ref.current);
}
// Remove the observer as soon as the component is unmounted
diff --git a/web/regression/javascript/components/CodeMirror.spec.js b/web/regression/javascript/components/CodeMirror.spec.js
index 5b347ea6c..ce75ead0a 100644
--- a/web/regression/javascript/components/CodeMirror.spec.js
+++ b/web/regression/javascript/components/CodeMirror.spec.js
@@ -19,14 +19,13 @@ describe('CodeMirror', ()=>{
let cmInstance, options={
lineNumbers: true,
mode: 'text/x-pgsql',
- }, cmObj = jasmine.createSpyObj('cmObj', {'setValue': ()=>{}, 'refresh': ()=>{}});
+ }, cmObj = jasmine.createSpyObj('cmObj', {'getValue':()=>'', 'setValue': ()=>{}, 'refresh': ()=>{}});
beforeEach(()=>{
jasmineEnzyme();
spyOn(OrigCodeMirror, 'fromTextArea').and.returnValue(cmObj);
cmInstance = mount(
);
@@ -34,14 +33,12 @@ describe('CodeMirror', ()=>{
it('init', ()=>{
/* textarea ref passed to fromTextArea */
- expect(OrigCodeMirror.fromTextArea).toHaveBeenCalledWith(cmInstance.getDOMNode(), options);
+ expect(OrigCodeMirror.fromTextArea).toHaveBeenCalledWith(cmInstance.find('textarea').getDOMNode(), options);
expect(cmObj.setValue).toHaveBeenCalledWith('Init text');
- expect(cmObj.refresh).toHaveBeenCalled();
});
it('change value', ()=>{
cmInstance.setProps({value: 'the new text'});
expect(cmObj.setValue).toHaveBeenCalledWith('the new text');
- expect(cmObj.refresh).toHaveBeenCalled();
});
});
diff --git a/web/regression/javascript/jasmine_capture_warnings_beforeall.js b/web/regression/javascript/jasmine_capture_warnings_beforeall.js
index 15f4dd252..62da3cc20 100644
--- a/web/regression/javascript/jasmine_capture_warnings_beforeall.js
+++ b/web/regression/javascript/jasmine_capture_warnings_beforeall.js
@@ -9,15 +9,15 @@
/* eslint-disable no-console */
-// beforeAll(function () {
-// spyOn(console, 'warn').and.callThrough();
-// spyOn(console, 'error').and.callThrough();
-// });
+beforeAll(function () {
+ spyOn(console, 'warn').and.callThrough();
+ spyOn(console, 'error').and.callThrough();
+});
-// afterEach(function (done) {
-// setTimeout(function () {
-// expect(console.warn).not.toHaveBeenCalled();
-// expect(console.error).not.toHaveBeenCalled();
-// done();
-// }, 0);
-// });
+afterEach(function (done) {
+ setTimeout(function () {
+ expect(console.warn).not.toHaveBeenCalled();
+ expect(console.error).not.toHaveBeenCalled();
+ done();
+ }, 0);
+});