1) Fixed schema diff workspace button is disabled for the first tab.

2) Adhoc servers should connect with service file and open the Query/PSQL tool.
This commit is contained in:
Akshay Joshi 2024-12-18 18:19:13 +05:30
parent 8af25ba0c1
commit fdf5d12196
5 changed files with 89 additions and 16 deletions

View File

@ -20,6 +20,7 @@ Bundled PostgreSQL Utilities
New features
************
| `Issue #6513 <https://github.com/pgadmin-org/pgadmin4/issues/6513>`_ - Change button labels and color in delete confirmation dialog for all objects to improve UX.
| `Issue #7708 <https://github.com/pgadmin-org/pgadmin4/issues/7708>`_ - Enhanced pgAdmin 4 with support for Workspace layouts.
Housekeeping

View File

@ -61,12 +61,27 @@ def index():
)
@pga_login_required
def adhoc_connect_server():
required_args = ['host', 'port', 'user']
required_args = ['server_name', 'did']
data = request.form if request.form else json.loads(
request.data
)
# Loop through data and if found any value is blank string then
# convert it to None as after porting into React, from frontend
# '' blank string is coming as a value instead of null.
for item in data:
if data[item] == '':
data[item] = None
# Some fields can be provided with service file so they are optional
if 'service' in data and not data['service']:
required_args.extend([
'host',
'port',
'user'
])
for arg in required_args:
if arg not in data:
return make_json_response(
@ -95,24 +110,28 @@ def adhoc_connect_server():
data['connection_params'] = connection_params
# Fetch all the new data in case of non-existing servers
new_host = data.get('host', None)
new_port = data.get('port', None)
new_db = data.get('database_name', None)
if new_db is None:
new_db = data.get('did')
new_username = data.get('user')
new_role = data.get('role', None)
new_server_name = data.get('server_name', None)
new_service = data.get('service', None)
try:
server = None
if config.CONFIG_DATABASE_URI is not None and \
len(config.CONFIG_DATABASE_URI) > 0:
# Filter out all the servers with the below combination.
servers = Server.query.filter_by(host=data['host'],
port=data['port'],
servers = Server.query.filter_by(host=new_host,
port=new_port,
maintenance_db=new_db,
username=new_username,
name=new_server_name,
role=new_role
role=new_role,
service=new_service
).all()
# If found matching servers then compare the connection_params as
@ -123,12 +142,13 @@ def adhoc_connect_server():
server = existing_server
break
else:
server = Server.query.filter_by(host=data['host'],
port=data['port'],
server = Server.query.filter_by(host=new_host,
port=new_port,
maintenance_db=new_db,
username=new_username,
name=new_server_name,
role=new_role,
service=new_service,
connection_params=connection_params
).first()
@ -156,12 +176,12 @@ def adhoc_connect_server():
user_id=current_user.id,
servergroup_id=data.get('gid', 1),
name=new_server_name,
host=data.get('host', None),
port=data.get('port'),
host=new_host,
port=new_port,
maintenance_db=new_db,
username=new_username,
role=new_role,
service=data.get('service', None),
service=new_service,
connection_params=connection_params,
is_adhoc=1
)

View File

@ -28,6 +28,7 @@ import * as showQueryTool from '../../../../tools/sqleditor/static/js/show_query
import { getTitle, generateTitle } from '../../../../tools/sqleditor/static/js/sqleditor_title';
import usePreferences from '../../../../preferences/static/js/store';
import { BROWSER_PANELS } from '../../../../browser/static/js/constants';
import { isEmptyString } from '../../../../static/js/validators';
class AdHocConnectionSchema extends BaseUISchema {
constructor(connectExistingServer, initValues={}) {
@ -183,11 +184,11 @@ class AdHocConnectionSchema extends BaseUISchema {
deps: ['sid', 'connected'],
disabled: (state) => state.sid,
}, {
id: 'host', label: gettext('Host name/address'), type: 'text', noEmpty: true,
id: 'host', label: gettext('Host name/address'), type: 'text',
deps: ['sid', 'connected'],
disabled: (state) => state.sid,
}, {
id: 'port', label: gettext('Port'), type: 'int', min: 1, max: 65535, noEmpty: true,
id: 'port', label: gettext('Port'), type: 'int', min: 1, max: 65535,
deps: ['sid', 'connected'],
disabled: (state) => state.sid,
},{
@ -215,7 +216,7 @@ class AdHocConnectionSchema extends BaseUISchema {
}
}, {
id: 'user', label: gettext('User'), deps: ['sid', 'connected'],
noEmpty: true, controlProps: {creatable: true},
controlProps: {creatable: true},
type: (state) => {
if (state?.sid) {
return {
@ -261,8 +262,54 @@ class AdHocConnectionSchema extends BaseUISchema {
}
];
}
}
validate(state, setError) {
let errmsg = null;
if (isEmptyString(state.service)) {
errmsg = gettext('Either Host name or Service must be specified.');
if(isEmptyString(state.host)) {
setError('host', errmsg);
return true;
} else {
setError('host', null);
}
/* Hostname, IP address validate */
if (state.host) {
// Check for leading and trailing spaces.
if (/(^\s)|(\s$)/.test(state.host)){
errmsg = gettext('Host name must be valid hostname or IPv4 or IPv6 address.');
setError('host', errmsg);
return true;
} else {
setError('host', null);
}
}
if(isEmptyString(state.username)) {
errmsg = gettext('Username must be specified.');
setError('username', errmsg);
return true;
} else {
setError('username', null);
}
if(isEmptyString(state.port)) {
errmsg = gettext('Port must be specified.');
setError('port', errmsg);
return true;
} else {
setError('port', null);
}
} else {
_.each(['host', 'db', 'username', 'port'], (item) => {
setError(item, null);
});
}
return false;
}
}
export default function AdHocConnection({mode}) {
const [connecting, setConnecting] = useState(false);
@ -313,6 +360,7 @@ export default function AdHocConnection({mode}) {
const openQueryTool = (respData, formData)=>{
const transId = commonUtils.getRandomInt(1, 9999999);
let db_name = _.isNil(formData.database_name) ? formData.did : formData.database_name;
let user_name = formData.role || formData.user || respData.data.user.name;
let parentData = {
server_group: {_id: 1},
@ -328,7 +376,7 @@ export default function AdHocConnection({mode}) {
};
const gridUrl = showQueryTool.generateUrl(transId, parentData, null);
const title = getTitle(pgAdmin, preferencesStore.getPreferencesForModule('browser'), null, false, formData.server_name, db_name, formData.role || formData.user);
const title = getTitle(pgAdmin, preferencesStore.getPreferencesForModule('browser'), null, false, formData.server_name, db_name, user_name);
showQueryTool.launchQueryTool(pgWindow.pgAdmin.Tools.SQLEditor, transId, gridUrl, title, {
user: formData.user,
role: formData.role,
@ -338,12 +386,13 @@ export default function AdHocConnection({mode}) {
const openPSQLTool = (respData, formData)=> {
const transId = commonUtils.getRandomInt(1, 9999999);
let db_name = _.isNil(formData.database_name) ? formData.did : formData.database_name;
let user_name = formData.role || formData.user || respData.data.user.name;
let panelTitle = '';
// Set psql tab title as per prefrences setting.
let title_data = {
'database': db_name ? _.unescape(db_name) : 'postgres' ,
'username': formData.user,
'username': user_name,
'server': formData.server_name,
'type': 'psql_tool',
};

View File

@ -76,7 +76,8 @@ export function WorkspaceProvider({children}) {
const hasOpenTabs = (forWs)=>{
const wsConfig = config.find((i)=>i.workspace == forWs);
if(wsConfig) {
return Boolean(pgAdmin.Browser.docker[wsConfig.docker]?.layoutObj?.getRootElement().querySelector('.dock-tab'));
//return Boolean(pgAdmin.Browser.docker[wsConfig.docker]?.layoutObj?.getRootElement().querySelector('.dock-tab'));
return Boolean(pgAdmin.Browser.docker[wsConfig.docker]?.layoutObj?.getLayout()?.dockbox?.children?.[0]?.tabs?.length);
}
return true;
};

View File

@ -55,9 +55,11 @@ function WorkspaceButton({menuItem, value, ...props}) {
setDisabled(!hasOpenTabs(value));
});
const deregChange = layout.eventBus.registerListener(LAYOUT_EVENTS.CHANGE, ()=>{
console.log(layout);
setDisabled(!hasOpenTabs(value));
});
const deregRemove = layout.eventBus.registerListener(LAYOUT_EVENTS.REMOVE, ()=>{
console.log(layout);
setDisabled(!hasOpenTabs(value));
});