1) Fixed an issue where loadingText message is not shown in SchemaView.
2) Fixed SonarQube Bugs and Code Smells.pull/8395/head
parent
684818def1
commit
22b7ae6cdc
|
@ -777,9 +777,6 @@ class ServerNode(PGChildNodeView):
|
||||||
request.data
|
request.data
|
||||||
)
|
)
|
||||||
|
|
||||||
old_server_name = ''
|
|
||||||
if 'name' in data:
|
|
||||||
old_server_name = server.name
|
|
||||||
if 'db_res' in data:
|
if 'db_res' in data:
|
||||||
data['db_res'] = ','.join(data['db_res'])
|
data['db_res'] = ','.join(data['db_res'])
|
||||||
|
|
||||||
|
|
|
@ -425,7 +425,7 @@ def migrate_saved_passwords(master_key, master_password):
|
||||||
servers_with_pwd_in_os_secret)
|
servers_with_pwd_in_os_secret)
|
||||||
# Update driver manager with new passwords
|
# Update driver manager with new passwords
|
||||||
try:
|
try:
|
||||||
update_session_manager(saved_password_servers)
|
update_session_manager(current_user.id, saved_password_servers)
|
||||||
except Exception:
|
except Exception:
|
||||||
current_app.logger.warning(
|
current_app.logger.warning(
|
||||||
'Error while updating session manger')
|
'Error while updating session manger')
|
||||||
|
@ -497,7 +497,7 @@ def delete_saved_passwords_from_os_secret_storage(servers):
|
||||||
|
|
||||||
if len(servers) > 0:
|
if len(servers) > 0:
|
||||||
for ser in servers:
|
for ser in servers:
|
||||||
server, is_password_saved, is_tunnel_password_saved = ser
|
server, _, _ = ser
|
||||||
server_name = KEY_RING_USERNAME_FORMAT.format(server.name,
|
server_name = KEY_RING_USERNAME_FORMAT.format(server.name,
|
||||||
server.id)
|
server.id)
|
||||||
server_password = keyring.get_password(
|
server_password = keyring.get_password(
|
||||||
|
@ -550,7 +550,7 @@ def update_session_manager(user_id=None, servers=None):
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def get_replication_type(conn, sversion):
|
def get_replication_type(conn, sversion):
|
||||||
|
|
|
@ -187,7 +187,7 @@ export default class MainMenuFactory {
|
||||||
const mi = getNewMenuItem(i);
|
const mi = getNewMenuItem(i);
|
||||||
if(!mi) return;
|
if(!mi) return;
|
||||||
|
|
||||||
if(i.category??'common' != 'common') {
|
if((i.category??'common') != 'common') {
|
||||||
const cmi = getMenuCategory(i.category);
|
const cmi = getMenuCategory(i.category);
|
||||||
if(cmi) {
|
if(cmi) {
|
||||||
cmi.addMenuItems([...applySeparators(mi)]);
|
cmi.addMenuItems([...applySeparators(mi)]);
|
||||||
|
|
|
@ -349,7 +349,7 @@ define('pgadmin.browser', [
|
||||||
const getFullPath = (currPath, currMenu)=>{
|
const getFullPath = (currPath, currMenu)=>{
|
||||||
if(currMenu.node) {
|
if(currMenu.node) {
|
||||||
return currPath.concat([currMenu.node]);
|
return currPath.concat([currMenu.node]);
|
||||||
} else if(currMenu.category??'common' != 'common') {
|
} else if((currMenu.category??'common') != 'common') {
|
||||||
const currCat = self.menu_categories[currMenu.category];
|
const currCat = self.menu_categories[currMenu.category];
|
||||||
if(currCat?.category) {
|
if(currCat?.category) {
|
||||||
return getFullPath(currPath.concat([currMenu.category]), currCat);
|
return getFullPath(currPath.concat([currMenu.category]), currCat);
|
||||||
|
|
|
@ -551,7 +551,7 @@ def logs(log_format=None, disp_format=None, sid=None, page=0):
|
||||||
status, res = g.conn.execute_scalar(sql)
|
status, res = g.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
if not res or len(res) < 0:
|
if not res or len(res) <= 0:
|
||||||
return ajax_response(
|
return ajax_response(
|
||||||
response={'logs_disabled': True},
|
response={'logs_disabled': True},
|
||||||
status=200
|
status=200
|
||||||
|
@ -594,7 +594,7 @@ def logs(log_format=None, disp_format=None, sid=None, page=0):
|
||||||
{"error_severity": _tmp_log['error_severity'],
|
{"error_severity": _tmp_log['error_severity'],
|
||||||
"timestamp": _tmp_log['timestamp'],
|
"timestamp": _tmp_log['timestamp'],
|
||||||
"message": _tmp_log['message']})
|
"message": _tmp_log['message']})
|
||||||
except Exception as e:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# CSV format
|
# CSV format
|
||||||
|
@ -605,12 +605,10 @@ def logs(log_format=None, disp_format=None, sid=None, page=0):
|
||||||
final_cols.append({"error_severity": _tmp_log[11],
|
final_cols.append({"error_severity": _tmp_log[11],
|
||||||
"timestamp": _tmp_log[0],
|
"timestamp": _tmp_log[0],
|
||||||
"message": _tmp_log[13]})
|
"message": _tmp_log[13]})
|
||||||
except Exception as e:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
col1 = []
|
|
||||||
col2 = []
|
|
||||||
_pattern = re.compile(LOG_STATEMENTS)
|
_pattern = re.compile(LOG_STATEMENTS)
|
||||||
for f in final_res:
|
for f in final_res:
|
||||||
tmp = re.search(LOG_STATEMENTS, f)
|
tmp = re.search(LOG_STATEMENTS, f)
|
||||||
|
|
|
@ -272,8 +272,6 @@ function ActiveOnlyHeader({activeOnly, setActiveOnly}) {
|
||||||
ActiveOnlyHeader.propTypes = {
|
ActiveOnlyHeader.propTypes = {
|
||||||
activeOnly: PropTypes.bool,
|
activeOnly: PropTypes.bool,
|
||||||
setActiveOnly: PropTypes.func,
|
setActiveOnly: PropTypes.func,
|
||||||
refresh: PropTypes.bool,
|
|
||||||
setRefresh: PropTypes.func,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function Dashboard({
|
function Dashboard({
|
||||||
|
@ -533,7 +531,7 @@ function Dashboard({
|
||||||
maxSize: 35,
|
maxSize: 35,
|
||||||
minSize: 35,
|
minSize: 35,
|
||||||
id: 'btn-terminate',
|
id: 'btn-terminate',
|
||||||
cell: getTerminateCell(pgAdmin, sid, did, canTakeAction, setRefresh, ()=>setRefresh(!refresh)),
|
cell: getTerminateCell(pgAdmin, sid, did, canTakeAction, ()=>setRefresh(!refresh)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: () => null,
|
header: () => null,
|
||||||
|
@ -544,7 +542,7 @@ function Dashboard({
|
||||||
maxSize: 35,
|
maxSize: 35,
|
||||||
minSize: 35,
|
minSize: 35,
|
||||||
id: 'btn-cancel',
|
id: 'btn-cancel',
|
||||||
cell: getCancelCell(pgAdmin, sid, did, canTakeAction, setRefresh, ()=>setRefresh(!refresh)),
|
cell: getCancelCell(pgAdmin, sid, did, canTakeAction, ()=>setRefresh(!refresh)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: () => null,
|
header: () => null,
|
||||||
|
@ -886,7 +884,7 @@ function Dashboard({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data && res.data['logs_disabled']) {
|
if (res?.data?.['logs_disabled']) {
|
||||||
setSsMsg(gettext('Please enable the logging to view the server logs or check the log file is in place or not.'));
|
setSsMsg(gettext('Please enable the logging to view the server logs or check the log file is in place or not.'));
|
||||||
} else {
|
} else {
|
||||||
setDashData(parseData(res.data));
|
setDashData(parseData(res.data));
|
||||||
|
@ -938,7 +936,7 @@ function Dashboard({
|
||||||
// we want to show 'idle in transaction', 'active', 'active in transaction', and future non-blank, non-"idle" status values
|
// we want to show 'idle in transaction', 'active', 'active in transaction', and future non-blank, non-"idle" status values
|
||||||
return dashData[0]['activity']?.filter((r)=>(r.state && r.state != '' && r.state != 'idle'));
|
return dashData[0]['activity']?.filter((r)=>(r.state && r.state != '' && r.state != 'idle'));
|
||||||
}
|
}
|
||||||
return dashData && dashData[0] && dashData[0]['activity'] || [];
|
return dashData?.[0]?.['activity'] || [];
|
||||||
}, [dashData, activeOnly, mainTabVal]);
|
}, [dashData, activeOnly, mainTabVal]);
|
||||||
|
|
||||||
const showDefaultContents = () => {
|
const showDefaultContents = () => {
|
||||||
|
@ -1089,7 +1087,7 @@ function Dashboard({
|
||||||
tableNoBorder={false}
|
tableNoBorder={false}
|
||||||
customHeader={<ActiveOnlyHeader activeOnly={activeOnly} setActiveOnly={setActiveOnly} refresh={refresh} setRefresh={setRefresh}/>}
|
customHeader={<ActiveOnlyHeader activeOnly={activeOnly} setActiveOnly={setActiveOnly} refresh={refresh} setRefresh={setRefresh}/>}
|
||||||
columns={activityColumns}
|
columns={activityColumns}
|
||||||
data={(dashData !== undefined && dashData[0] && filteredDashData) || []}
|
data={(dashData?.[0] && filteredDashData) || []}
|
||||||
schema={activeQSchemaObj}
|
schema={activeQSchemaObj}
|
||||||
></PgTable>
|
></PgTable>
|
||||||
</SectionContainer>
|
</SectionContainer>
|
||||||
|
@ -1098,7 +1096,7 @@ function Dashboard({
|
||||||
caveTable={false}
|
caveTable={false}
|
||||||
tableNoBorder={false}
|
tableNoBorder={false}
|
||||||
columns={databaseLocksColumns}
|
columns={databaseLocksColumns}
|
||||||
data={(dashData !== undefined && dashData[0] && dashData[0]['locks']) || []}
|
data={(dashData?.[0]?.['locks']) || []}
|
||||||
></PgTable>
|
></PgTable>
|
||||||
</SectionContainer>
|
</SectionContainer>
|
||||||
<SectionContainer title={gettext('Prepared Transactions')} style={{height: 'auto', minHeight: '200px', maxHeight:'400px', paddingBottom: '20px'}}>
|
<SectionContainer title={gettext('Prepared Transactions')} style={{height: 'auto', minHeight: '200px', maxHeight:'400px', paddingBottom: '20px'}}>
|
||||||
|
@ -1106,7 +1104,7 @@ function Dashboard({
|
||||||
caveTable={false}
|
caveTable={false}
|
||||||
tableNoBorder={false}
|
tableNoBorder={false}
|
||||||
columns={databasePreparedColumns}
|
columns={databasePreparedColumns}
|
||||||
data={(dashData !== undefined && dashData[0] && dashData[0]['prepared']) || []}
|
data={(dashData?.[0]?.['prepared']) || []}
|
||||||
></PgTable>
|
></PgTable>
|
||||||
</SectionContainer>
|
</SectionContainer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -122,7 +122,6 @@ class AzureCredSchema extends BaseUISchema {
|
||||||
auth_code: ''
|
auth_code: ''
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
// TODO:: Show error message.
|
|
||||||
console.error(
|
console.error(
|
||||||
err instanceof Error ?
|
err instanceof Error ?
|
||||||
err : Error(gettext('Something went wrong'))
|
err : Error(gettext('Something went wrong'))
|
||||||
|
|
|
@ -68,7 +68,6 @@ class GoogleCredSchema extends BaseUISchema{
|
||||||
obj.fieldOptions.verification_ack();
|
obj.fieldOptions.verification_ack();
|
||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
// FIXME:: Show error message.
|
|
||||||
console.error(
|
console.error(
|
||||||
err instanceof Error ?
|
err instanceof Error ?
|
||||||
err : Error(gettext('Something went wrong'))
|
err : Error(gettext('Something went wrong'))
|
||||||
|
@ -505,7 +504,7 @@ class GoogleClusterSchema extends BaseUISchema {
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(data, setErr) {
|
validate(data, setErr) {
|
||||||
if ( !isEmptyString(data.name) && (!/^(?=[a-z])[a-z0-9\-]*$/.test(data.name) || data.name.length > 97)) {
|
if ( !isEmptyString(data.name) && (!/^(?=[a-z])[a-z0-9-]*$/.test(data.name) || data.name.length > 97)) {
|
||||||
setErr('name',gettext('Name must only contain lowercase letters, numbers, and hyphens.Should start with a letter and must be 97 characters or less'));
|
setErr('name',gettext('Name must only contain lowercase letters, numbers, and hyphens.Should start with a letter and must be 97 characters or less'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,11 +111,11 @@ export default class FileManagerModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
show(params, onOK, onCancel, modalObj) {
|
async show(params, onOK, onCancel, modalObj) {
|
||||||
let {name: browser} = getBrowser();
|
let {name: browser} = getBrowser();
|
||||||
if(browser == 'Electron') {
|
if(browser == 'Electron') {
|
||||||
try {
|
try {
|
||||||
this.showNative(params, onOK, onCancel);
|
await this.showNative(params, onOK, onCancel);
|
||||||
} catch {
|
} catch {
|
||||||
// Fall back to internal
|
// Fall back to internal
|
||||||
this.showInternal(params, onOK, onCancel, modalObj);
|
this.showInternal(params, onOK, onCancel, modalObj);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { usePgAdmin } from '../../static/js/PgAdminProvider';
|
||||||
import { LAYOUT_EVENTS, LayoutDockerContext } from '../../static/js/helpers/Layout';
|
import { LAYOUT_EVENTS, LayoutDockerContext } from '../../static/js/helpers/Layout';
|
||||||
import usePreferences from '../../preferences/static/js/store';
|
import usePreferences from '../../preferences/static/js/store';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
export default function ObjectNodeProperties({panelId, node, treeNodeInfo, nodeData, actionType, formType, onEdit, onSave, onClose,
|
export default function ObjectNodeProperties({panelId, node, treeNodeInfo, nodeData, actionType, formType, onEdit, onSave, onClose,
|
||||||
isActive, setIsStale, isStale}) {
|
isActive, setIsStale, isStale}) {
|
||||||
|
@ -44,7 +45,7 @@ export default function ObjectNodeProperties({panelId, node, treeNodeInfo, nodeD
|
||||||
let updatedData = ['table', 'partition'].includes(nodeType) && !_.isEmpty(nodeData.rows_cnt) ? {rows_cnt: nodeData.rows_cnt} : undefined;
|
let updatedData = ['table', 'partition'].includes(nodeType) && !_.isEmpty(nodeData.rows_cnt) ? {rows_cnt: nodeData.rows_cnt} : undefined;
|
||||||
|
|
||||||
const objToString = (obj) => (
|
const objToString = (obj) => (
|
||||||
(obj && typeof obj === 'object') ? Object.keys(obj).sort().reduce(
|
(obj && typeof obj === 'object') ? Object.keys(obj).sort((a, b)=>a.localeCompare(b)).reduce(
|
||||||
(acc, key) => (acc + `${key}=` + objToString(obj[key])), ''
|
(acc, key) => (acc + `${key}=` + objToString(obj[key])), ''
|
||||||
) : String(obj)
|
) : String(obj)
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import gettext from 'sources/gettext';
|
import gettext from 'sources/gettext';
|
||||||
import url_for from 'sources/url_for';
|
import url_for from 'sources/url_for';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
@ -329,7 +329,6 @@ class AdHocConnectionSchema extends BaseUISchema {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AdHocConnection({mode}) {
|
export default function AdHocConnection({mode}) {
|
||||||
const [connecting, setConnecting] = useState(false);
|
|
||||||
const api = getApiInstance();
|
const api = getApiInstance();
|
||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
const pgAdmin = usePgAdmin();
|
const pgAdmin = usePgAdmin();
|
||||||
|
@ -337,7 +336,6 @@ export default function AdHocConnection({mode}) {
|
||||||
const {currentWorkspace} = useWorkspace();
|
const {currentWorkspace} = useWorkspace();
|
||||||
|
|
||||||
const connectExistingServer = async (sid, user, formData, connectCallback) => {
|
const connectExistingServer = async (sid, user, formData, connectCallback) => {
|
||||||
setConnecting(true);
|
|
||||||
try {
|
try {
|
||||||
let {data: respData} = await api({
|
let {data: respData} = await api({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -350,7 +348,6 @@ export default function AdHocConnection({mode}) {
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
data: formData
|
data: formData
|
||||||
});
|
});
|
||||||
setConnecting(false);
|
|
||||||
connectCallback?.(respData.data);
|
connectCallback?.(respData.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if(!error.response) {
|
if(!error.response) {
|
||||||
|
@ -360,7 +357,6 @@ export default function AdHocConnection({mode}) {
|
||||||
return (
|
return (
|
||||||
<ConnectServerContent
|
<ConnectServerContent
|
||||||
closeModal={()=>{
|
closeModal={()=>{
|
||||||
setConnecting(false);
|
|
||||||
closeModal();
|
closeModal();
|
||||||
}}
|
}}
|
||||||
data={error.response?.data?.result}
|
data={error.response?.data?.result}
|
||||||
|
@ -451,21 +447,18 @@ export default function AdHocConnection({mode}) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSaveClick = async (isNew, formData) => {
|
const onSaveClick = async (isNew, formData) => {
|
||||||
setConnecting(true);
|
|
||||||
try {
|
try {
|
||||||
let {data: respData} = await api({
|
let {data: respData} = await api({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: url_for('workspace.adhoc_connect_server'),
|
url: url_for('workspace.adhoc_connect_server'),
|
||||||
data: JSON.stringify(formData)
|
data: JSON.stringify(formData)
|
||||||
});
|
});
|
||||||
setConnecting(false);
|
|
||||||
if (mode == WORKSPACES.QUERY_TOOL) {
|
if (mode == WORKSPACES.QUERY_TOOL) {
|
||||||
openQueryTool(respData, formData);
|
openQueryTool(respData, formData);
|
||||||
} else if (mode == WORKSPACES.PSQL_TOOL) {
|
} else if (mode == WORKSPACES.PSQL_TOOL) {
|
||||||
openPSQLTool(respData, formData);
|
openPSQLTool(respData, formData);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setConnecting(false);
|
|
||||||
if(!error.response) {
|
if(!error.response) {
|
||||||
pgAdmin.Browser.notifier.pgNotifier('error', error, 'Connection error', gettext('Connect to server.'));
|
pgAdmin.Browser.notifier.pgNotifier('error', error, 'Connection error', gettext('Connect to server.'));
|
||||||
} else {
|
} else {
|
||||||
|
@ -508,7 +501,7 @@ export default function AdHocConnection({mode}) {
|
||||||
viewHelperProps={{
|
viewHelperProps={{
|
||||||
mode: 'create',
|
mode: 'create',
|
||||||
}}
|
}}
|
||||||
loadingText={connecting ? 'Connecting...' : ''}
|
loadingText={'Connecting...'}
|
||||||
onSave={onSaveClick}
|
onSave={onSaveClick}
|
||||||
customSaveBtnName= {saveBtnName}
|
customSaveBtnName= {saveBtnName}
|
||||||
customCloseBtnName={''}
|
customCloseBtnName={''}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import React, {Fragment, useEffect, useMemo, useState } from 'react';
|
import React, {useEffect, useMemo, useState } from 'react';
|
||||||
import AppMenuBar from './AppMenuBar';
|
import AppMenuBar from './AppMenuBar';
|
||||||
import ObjectBreadcrumbs from './components/ObjectBreadcrumbs';
|
import ObjectBreadcrumbs from './components/ObjectBreadcrumbs';
|
||||||
import Layout, { LAYOUT_EVENTS, LayoutDocker, getDefaultGroup } from './helpers/Layout';
|
import Layout, { LAYOUT_EVENTS, LayoutDocker, getDefaultGroup } from './helpers/Layout';
|
||||||
|
|
|
@ -31,12 +31,9 @@ export default class Feature {
|
||||||
this.schemaState = schemaState;
|
this.schemaState = schemaState;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateColumns(/* { pgAdmin, columns, columnVisibility, options } */) {}
|
generateColumns() {/*This is intentional (SonarQube)*/}
|
||||||
onTable(/* { table, options, classList } */) {}
|
onTable() {/*This is intentional (SonarQube)*/}
|
||||||
onRow(/* {
|
onRow() {/*This is intentional (SonarQube)*/}
|
||||||
index, row, rowRef, classList, attributes,
|
|
||||||
expandedRowContents, rowOptions, tableOptions
|
|
||||||
} */) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidFeatureClass(cls) {
|
function isValidFeatureClass(cls) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ export default class Reorder extends Feature {
|
||||||
<div
|
<div
|
||||||
className='reorder-cell'
|
className='reorder-cell'
|
||||||
data-handler-id={handlerId}
|
data-handler-id={handlerId}
|
||||||
ref={dragHandleRef ? dragHandleRef : null}>
|
ref={dragHandleRef || null}>
|
||||||
<DragIndicatorRoundedIcon fontSize="small" />
|
<DragIndicatorRoundedIcon fontSize="small" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -17,10 +17,9 @@ export const FieldControl = ({schemaId, item}) => {
|
||||||
return useMemo(() =>
|
return useMemo(() =>
|
||||||
<Control {...props}>
|
<Control {...props}>
|
||||||
{
|
{
|
||||||
children &&
|
children?.map(
|
||||||
children.map(
|
(child, idx) => <FieldControl key={idx} item={child}/>
|
||||||
(child, idx) => <FieldControl key={idx} item={child}/>
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</Control>, [schemaId, Control, props, children]
|
</Control>, [schemaId, Control, props, children]
|
||||||
);
|
);
|
||||||
|
|
|
@ -120,12 +120,12 @@ export default function SchemaDialogView({
|
||||||
const onSaveClick = () => {
|
const onSaveClick = () => {
|
||||||
// Do nothing when there is no change or there is an error
|
// Do nothing when there is no change or there is an error
|
||||||
if (
|
if (
|
||||||
!schemaState._changes || Object.keys(schemaState._changes) === 0 ||
|
!schemaState._changes || Object.keys(schemaState._changes).length === 0 ||
|
||||||
schemaState.errors.name
|
schemaState.errors.name
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
setLoaderText('Saving...');
|
setLoaderText(schemaState.customLoadingText || gettext('Saving...'));
|
||||||
|
|
||||||
if (!schema.warningText) {
|
if (!schema.warningText) {
|
||||||
save(schemaState.changes(true));
|
save(schemaState.changes(true));
|
||||||
|
|
|
@ -288,14 +288,14 @@ export class SchemaState extends DepListener {
|
||||||
this.dataStore.setState(_data);
|
this.dataStore.setState(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
accessPath(path=[], key) {
|
accessPath(path, key) {
|
||||||
return this.__pathGenerator.cached(
|
return this.__pathGenerator.cached(
|
||||||
_.isUndefined(key) ? path : path.concat(key)
|
_.isUndefined(key) ? path : path.concat(key)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
value(path) {
|
value(path) {
|
||||||
if (!path || !path.length) return this.data;
|
if (!path?.length) return this.data;
|
||||||
return _.get(this.data, path);
|
return _.get(this.data, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,16 +99,16 @@ export const sessDataReducer = (state, action) => {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCHEMA_STATE_ACTIONS.MOVE_ROW:
|
case SCHEMA_STATE_ACTIONS.MOVE_ROW: {
|
||||||
rows = _.get(data, action.path)||[];
|
rows = _.get(data, action.path)||[];
|
||||||
var row = rows[action.oldIndex];
|
let row = rows[action.oldIndex];
|
||||||
rows.splice(action.oldIndex, 1);
|
rows.splice(action.oldIndex, 1);
|
||||||
rows.splice(action.newIndex, 0, row);
|
rows.splice(action.newIndex, 0, row);
|
||||||
|
|
||||||
_.set(data, action.path, rows);
|
_.set(data, action.path, rows);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SCHEMA_STATE_ACTIONS.CLEAR_DEFERRED_QUEUE:
|
case SCHEMA_STATE_ACTIONS.CLEAR_DEFERRED_QUEUE:
|
||||||
data.__deferred__ = [];
|
data.__deferred__ = [];
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -96,7 +96,7 @@ export function prepareData(val, createMode=false) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const flatternObject = (obj, base=[]) => Object.keys(obj).sort().reduce(
|
export const flatternObject = (obj, base=[]) => Object.keys(obj).sort((a, b)=>a.localeCompare(b)).reduce(
|
||||||
(r, k) => {
|
(r, k) => {
|
||||||
r = r.concat(k);
|
r = r.concat(k);
|
||||||
const value = obj[k];
|
const value = obj[k];
|
||||||
|
|
|
@ -101,8 +101,6 @@ export function schemaOptionsEvalulator({
|
||||||
|
|
||||||
_.set(options, fieldOptionsPath, fieldOptions);
|
_.set(options, fieldOptionsPath, fieldOptions);
|
||||||
|
|
||||||
const rowIndexes = [FIELD_OPTIONS];
|
|
||||||
|
|
||||||
rows?.forEach((row, idx) => {
|
rows?.forEach((row, idx) => {
|
||||||
const schemaPath = [...fieldPath, idx];
|
const schemaPath = [...fieldPath, idx];
|
||||||
const schemaOptions = _.get(options, schemaPath, {});
|
const schemaOptions = _.get(options, schemaPath, {});
|
||||||
|
@ -123,8 +121,6 @@ export function schemaOptionsEvalulator({
|
||||||
option: 'row', schema: field.schema, value: row, viewHelperProps,
|
option: 'row', schema: field.schema, value: row, viewHelperProps,
|
||||||
field, options: rowOptions, parentOptions: fieldOptions
|
field, options: rowOptions, parentOptions: fieldOptions
|
||||||
});
|
});
|
||||||
|
|
||||||
rowIndexes.push(idx);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ export const createFieldControls = ({
|
||||||
|
|
||||||
if(field.type === 'group') {
|
if(field.type === 'group') {
|
||||||
|
|
||||||
if (!field.id || (field.id in groups)) {
|
if (!field.id || (groups.includes(field.id))) {
|
||||||
throw new Error('Group-id must be unique within a schema.');
|
throw new Error('Group-id must be unique within a schema.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,6 @@ function UtilityViewContent({schema, treeNodeInfo, actionType, formType, onClose
|
||||||
}
|
}
|
||||||
|
|
||||||
UtilityViewContent.propTypes = {
|
UtilityViewContent.propTypes = {
|
||||||
panelId: PropTypes.string,
|
|
||||||
schema: PropTypes.object,
|
schema: PropTypes.object,
|
||||||
treeNodeInfo: PropTypes.object,
|
treeNodeInfo: PropTypes.object,
|
||||||
actionType: PropTypes.string,
|
actionType: PropTypes.string,
|
||||||
|
|
|
@ -155,7 +155,7 @@ export function Table({
|
||||||
// Render the UI for your table
|
// Render the UI for your table
|
||||||
const tableRef = useRef();
|
const tableRef = useRef();
|
||||||
let flatData = [];
|
let flatData = [];
|
||||||
let fetchMoreOnBottomReached = undefined;
|
let fetchMoreOnBottomReached;
|
||||||
let totalFetched = 0;
|
let totalFetched = 0;
|
||||||
let totalDBRowCount = 0;
|
let totalDBRowCount = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// pgAdmin 4 - PostgreSQL Tools
|
||||||
|
//
|
||||||
|
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||||
|
// This software is released under the PostgreSQL Licence
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import { useSingleAndDoubleClick } from '../../../custom_hooks';
|
import { useSingleAndDoubleClick } from '../../../custom_hooks';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -15,4 +24,4 @@ DoubleClickHandler.propTypes = {
|
||||||
onSingleClick: PropTypes.func,
|
onSingleClick: PropTypes.func,
|
||||||
onDoubleClick: PropTypes.func,
|
onDoubleClick: PropTypes.func,
|
||||||
children: CustomPropTypes.children
|
children: CustomPropTypes.children
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,7 +83,7 @@ function alert(title, text, onOkClick, okLabel = gettext('OK')) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No'), okIcon) {
|
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No'), okIcon = 'default') {
|
||||||
// bind the modal provider before calling
|
// bind the modal provider before calling
|
||||||
this.showModal(title, (closeModal) => {
|
this.showModal(title, (closeModal) => {
|
||||||
const onCancelClickClose = () => {
|
const onCancelClickClose = () => {
|
||||||
|
|
|
@ -175,7 +175,7 @@ class Notifier {
|
||||||
this.modal.alert(title, text, onOkClick, okLabel);
|
this.modal.alert(title, text, onOkClick, okLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'), okIcon) {
|
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'), okIcon='default') {
|
||||||
/* Use this if you want to use pgAdmin global notifier.
|
/* Use this if you want to use pgAdmin global notifier.
|
||||||
Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */
|
Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */
|
||||||
this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, okIcon);
|
this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, okIcon);
|
||||||
|
|
|
@ -379,7 +379,7 @@ export function evalFunc(obj, func, ...param) {
|
||||||
|
|
||||||
export function getBrowser() {
|
export function getBrowser() {
|
||||||
if(navigator.userAgent.indexOf('Electron') >= 0) {
|
if(navigator.userAgent.indexOf('Electron') >= 0) {
|
||||||
return {name: 'Electron', version: navigator.userAgent.match(/Electron\/([\d\.]+\d+)/)[1]};
|
return {name: 'Electron', version: /Electron\/([\d.]+\d+)/.exec(navigator.userAgent)[1]};
|
||||||
}
|
}
|
||||||
|
|
||||||
let ua=navigator.userAgent,tem,M=(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i).exec(ua) || [];
|
let ua=navigator.userAgent,tem,M=(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i).exec(ua) || [];
|
||||||
|
@ -388,7 +388,7 @@ export function getBrowser() {
|
||||||
return {name:'IE', version:(tem[1]||'')};
|
return {name:'IE', version:(tem[1]||'')};
|
||||||
}
|
}
|
||||||
if(ua.indexOf('Electron') >= 0) {
|
if(ua.indexOf('Electron') >= 0) {
|
||||||
return {name: 'Electron', version: ua.match(/Electron\/([\d\.]+\d+)/)[1]};
|
return {name: 'Electron', version: /Electron\/([\d.]+\d+)/.exec(ua)[1]};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(M[1]==='Chrome') {
|
if(M[1]==='Chrome') {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Box } from '@mui/material';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, {useState, useEffect, useContext, useRef, useLayoutEffect, useMemo, useCallback} from 'react';
|
import React, {useState, useEffect, useContext, useRef, useLayoutEffect, useMemo, useCallback} from 'react';
|
||||||
import {Row, useRowSelection} from 'react-data-grid';
|
import {Row, useRowSelection, useHeaderRowSelection} from 'react-data-grid';
|
||||||
import LockIcon from '@mui/icons-material/Lock';
|
import LockIcon from '@mui/icons-material/Lock';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import { QUERY_TOOL_EVENTS } from '../QueryToolConstants';
|
import { QUERY_TOOL_EVENTS } from '../QueryToolConstants';
|
||||||
|
@ -24,7 +24,6 @@ import gettext from 'sources/gettext';
|
||||||
import PgReactDataGrid from '../../../../../../static/js/components/PgReactDataGrid';
|
import PgReactDataGrid from '../../../../../../static/js/components/PgReactDataGrid';
|
||||||
import { isMac } from '../../../../../../static/js/keyboard_shortcuts';
|
import { isMac } from '../../../../../../static/js/keyboard_shortcuts';
|
||||||
import { measureText } from '../../../../../../static/js/utils';
|
import { measureText } from '../../../../../../static/js/utils';
|
||||||
import { useHeaderRowSelection } from 'react-data-grid';
|
|
||||||
|
|
||||||
export const ROWNUM_KEY = '$_pgadmin_rownum_key_$';
|
export const ROWNUM_KEY = '$_pgadmin_rownum_key_$';
|
||||||
export const GRID_ROW_SELECT_KEY = '$_pgadmin_gridrowselect_key_$';
|
export const GRID_ROW_SELECT_KEY = '$_pgadmin_gridrowselect_key_$';
|
||||||
|
@ -158,10 +157,9 @@ function SelectAllHeaderRenderer({isCellSelected}) {
|
||||||
}, [isRowSelected]);
|
}, [isRowSelected]);
|
||||||
|
|
||||||
return <div ref={cellRef} style={{width: '100%', height: '100%'}} onClick={onClick}
|
return <div ref={cellRef} style={{width: '100%', height: '100%'}} onClick={onClick}
|
||||||
tabIndex="0" onKeyDown={(e)=>dataGridExtras.handleShortcuts(e, true)}></div>;
|
tabIndex="-1" onKeyDown={(e)=>dataGridExtras.handleShortcuts(e, true)}></div>;
|
||||||
}
|
}
|
||||||
SelectAllHeaderRenderer.propTypes = {
|
SelectAllHeaderRenderer.propTypes = {
|
||||||
onAllRowsSelectionChange: PropTypes.func,
|
|
||||||
isCellSelected: PropTypes.bool,
|
isCellSelected: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -310,17 +310,19 @@ function TheMap({data}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
zoomControlWithHome.current._zoomHome = function () {
|
zoomControlWithHome.current._zoomHome = function () {
|
||||||
if (this.options.maxLength > 0) {
|
let obj = this;
|
||||||
this._map.fitBounds(this.options.homeCoordinates);
|
if (obj.options.maxLength > 0) {
|
||||||
|
obj._map.fitBounds(obj.options.homeCoordinates);
|
||||||
} else {
|
} else {
|
||||||
this.options.homeCoordinates && this._map.setView(this.options.homeCoordinates.getCenter(), this.options.homeZoom);
|
obj.options.homeCoordinates && obj._map.setView(obj.options.homeCoordinates.getCenter(), obj.options.homeZoom);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
zoomControlWithHome.current.onAdd = function (map) {
|
zoomControlWithHome.current.onAdd = function (map) {
|
||||||
|
let obj = this;
|
||||||
let controlName = 'leaflet-control-zoom',
|
let controlName = 'leaflet-control-zoom',
|
||||||
container = Leaflet.DomUtil.create('div', controlName + ' leaflet-bar'),
|
container = Leaflet.DomUtil.create('div', controlName + ' leaflet-bar'),
|
||||||
options = this.options;
|
options = obj.options;
|
||||||
|
|
||||||
if (options.homeCoordinates === null) {
|
if (options.homeCoordinates === null) {
|
||||||
options.homeCoordinates = homeCoordinates.current?.bounds;
|
options.homeCoordinates = homeCoordinates.current?.bounds;
|
||||||
|
@ -334,12 +336,12 @@ function TheMap({data}) {
|
||||||
|
|
||||||
let zoomHomeText = `<i class="fa fa-${options.zoomHomeIcon}"></i>`;
|
let zoomHomeText = `<i class="fa fa-${options.zoomHomeIcon}"></i>`;
|
||||||
|
|
||||||
this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle, controlName + '-in', container, this._zoomIn.bind(this));
|
obj._zoomInButton = obj._createButton(options.zoomInText, options.zoomInTitle, controlName + '-in', container, obj._zoomIn.bind(this));
|
||||||
this._createButton(zoomHomeText, options.zoomHomeTitle, controlName + '-home', container, this._zoomHome.bind(this));
|
obj._createButton(zoomHomeText, options.zoomHomeTitle, controlName + '-home', container, obj._zoomHome.bind(this));
|
||||||
this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle, controlName + '-out', container, this._zoomOut.bind(this));
|
obj._zoomOutButton = obj._createButton(options.zoomOutText, options.zoomOutTitle, controlName + '-out', container, obj._zoomOut.bind(this));
|
||||||
|
|
||||||
this._updateDisabled();
|
obj._updateDisabled();
|
||||||
map.on('zoomend zoomlevelschange', this._updateDisabled, this);
|
map.on('zoomend zoomlevelschange', obj._updateDisabled, this);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue