From b303693ae8904985fc0d1c9704e54db8eca25e3c Mon Sep 17 00:00:00 2001 From: Khushboo Vashi Date: Thu, 11 Jul 2024 10:26:42 +0530 Subject: [PATCH] Fix Dashboard minor UI issues. Fix the issue where PG logs doesn't display in CSV or JSON format even if it gets selected through the UI. --- web/pgadmin/dashboard/__init__.py | 15 +++- web/pgadmin/dashboard/static/js/Dashboard.jsx | 35 +++++---- .../static/js/components/RefreshButtons.jsx | 7 +- .../static/js/components/FormComponents.jsx | 2 +- web/pgadmin/static/js/components/PgTable.jsx | 74 +++++++++---------- 5 files changed, 69 insertions(+), 64 deletions(-) diff --git a/web/pgadmin/dashboard/__init__.py b/web/pgadmin/dashboard/__init__.py index dd331d007..de7976f57 100644 --- a/web/pgadmin/dashboard/__init__.py +++ b/web/pgadmin/dashboard/__init__.py @@ -536,16 +536,18 @@ def logs(log_format=None, disp_format=None, sid=None, page=0): status, _format = g.conn.execute_scalar(sql) # Check the requested format is available or not - log_format = '' if log_format == 'C' and 'csvlog' in _format: log_format = 'csvlog' elif log_format == 'J' and 'jsonlog' in _format: log_format = 'jsonlog' + else: + log_format = '' sql = render_template( "/".join([g.template_path, 'log_stat.sql']), log_format=log_format, conn=g.conn ) + status, res = g.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=res) @@ -557,6 +559,12 @@ def logs(log_format=None, disp_format=None, sid=None, page=0): file_stat = json.loads(res[0]) + if file_stat <= 0: + return ajax_response( + response={'logs_disabled': True}, + status=200 + ) + _start = 0 _end = ON_DEMAND_LOG_COUNT page = int(page) @@ -573,13 +581,12 @@ def logs(log_format=None, disp_format=None, sid=None, page=0): log_format=log_format, conn=g.conn ) status, res = g.conn.execute_dict(sql) - if not status: return internal_server_error(errormsg=res) final_res = res['rows'][0]['pg_read_file'].split('\n') # Json format - if log_format == 'J': + if log_format == 'jsonlog': for f in final_res: try: _tmp_log = json.loads(f) @@ -591,7 +598,7 @@ def logs(log_format=None, disp_format=None, sid=None, page=0): pass # CSV format - elif log_format == 'C': + elif log_format == 'csvlog': for f in final_res: try: _tmp_log = f.split(',') diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx index 6cd191577..ad4a8b457 100644 --- a/web/pgadmin/dashboard/static/js/Dashboard.jsx +++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx @@ -83,15 +83,19 @@ const Root = styled('div')(({theme}) => ({ }, '& .Dashboard-textArea': { height: '88%', - } + }, + '& .RefreshButtons': { + display: 'flex', + }, + '& .Mui-disabled': { + pointerEvents: 'auto', + }, }, }, }, '& .Dashboard-emptyPanel': { width: '100%', - height: '100%', background: theme.otherVars.emptySpaceBg, - overflow: 'auto', padding: '8px', display: 'flex', }, @@ -234,7 +238,7 @@ function getCancelCell(pgAdmin, sid, did, canTakeAction, onSuccess) { function CustomRefresh({refresh, setRefresh}) { return ( - { + { e.preventDefault(); setRefresh(!refresh); }}/> @@ -245,12 +249,8 @@ CustomRefresh.propTypes = { setRefresh: PropTypes.func, }; -function ActiveOnlyHeader({activeOnly, setActiveOnly, refresh, setRefresh}) { - return ( - { - e.preventDefault(); - setRefresh(!refresh); - }}/> +function ActiveOnlyHeader({activeOnly, setActiveOnly}) { + return ( + /> ); } ActiveOnlyHeader.propTypes = { @@ -768,7 +768,6 @@ function Dashboard({ enableFilters: true, minSize: 50, size: 80, - cell: ({ value }) => String(value) }, ]; @@ -824,8 +823,10 @@ function Dashboard({ let _format = res.data; let _frm = [ {'label': gettext('Text'), 'value': 'T', 'disabled': !_format.includes('stderr')}, - {'label': gettext('JSON'), 'value': 'J', 'disabled': !_format.includes('jsonlog')}, - {'label': gettext('CSV'), 'value': 'C', 'disabled': !_format.includes('csvlog')} + {'label': gettext('JSON'), 'value': 'J', 'disabled': !_format.includes('jsonlog'), + tooltip: gettext('Enable JSON logging from postgresql.conf.')}, + {'label': gettext('CSV'), 'value': 'C', 'disabled': !_format.includes('csvlog'), + tooltip: gettext('Enable CSV logging from postgres.conf.')} ]; setLogConfigFormat(_frm); }) @@ -840,7 +841,6 @@ function Dashboard({ useEffect(() => { - if (mainTabVal == 0) return; // disable replication tab if(!treeNodeInfo?.server?.replication_type && mainTabVal == 5) { setMainTabVal(0); @@ -879,7 +879,7 @@ function Dashboard({ if (node) { setSsMsg(gettext('Loading logs...')); setDashData([]); - if (mainTabVal != 4 && mainTabVal != 5) { + if (mainTabVal == 1 || mainTabVal == 2 || mainTabVal == 3) { api({ url: url, type: 'GET', @@ -1081,6 +1081,7 @@ function Dashboard({ {!_.isUndefined(preferences) && preferences.show_activity && ( + } caveTable={false} tableNoBorder={false} columns={databaseLocksColumns} @@ -1103,7 +1103,6 @@ function Dashboard({ } caveTable={false} tableNoBorder={false} columns={databasePreparedColumns} diff --git a/web/pgadmin/dashboard/static/js/components/RefreshButtons.jsx b/web/pgadmin/dashboard/static/js/components/RefreshButtons.jsx index c329376de..357f06e4f 100644 --- a/web/pgadmin/dashboard/static/js/components/RefreshButtons.jsx +++ b/web/pgadmin/dashboard/static/js/components/RefreshButtons.jsx @@ -23,11 +23,11 @@ const StyledPgIconButton = styled(PgIconButton)(({theme}) => ({ } })); -export default function RefreshButton({onClick}) { +export default function RefreshButton({onClick, noBorder=true}) { return ( } onClick={onClick} @@ -39,5 +39,6 @@ export default function RefreshButton({onClick}) { } RefreshButton.propTypes = { - onClick: PropTypes.func + onClick: PropTypes.func, + noBorder: PropTypes.bool }; diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx index fa0cd2c33..efd8aeffe 100644 --- a/web/pgadmin/static/js/components/FormComponents.jsx +++ b/web/pgadmin/static/js/components/FormComponents.jsx @@ -676,7 +676,7 @@ export const InputToggle = forwardRef(({ cid, value, onChange, options, disabled const isDisabled = disabled || option.disabled || (readonly && !isSelected); return ; }) } diff --git a/web/pgadmin/static/js/components/PgTable.jsx b/web/pgadmin/static/js/components/PgTable.jsx index b9f2e141f..9782d4ec2 100644 --- a/web/pgadmin/static/js/components/PgTable.jsx +++ b/web/pgadmin/static/js/components/PgTable.jsx @@ -118,46 +118,44 @@ export function Table({ columns, data, hasSelectRow, schema, sortOptions, tableP let totalFetched = 0; let totalDBRowCount = 0; - if (loadNextPage) { - //Infinite scrolling - const { _data, fetchNextPage, isFetching } = - useInfiniteQuery({ - queryKey: ['logs'], - queryFn: async () => { - const fetchedData = await loadNextPage(); - return fetchedData; - }, - initialPageParam: 0, - getNextPageParam: (_lastGroup, groups) => groups.length, - refetchOnWindowFocus: false, - placeholderData: keepPreviousData, - }); - - flatData = _data || []; - totalFetched = flatData.length; - - //called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table - fetchMoreOnBottomReached = React.useCallback( - (containerRefElement = HTMLDivElement | null) => { - if (containerRefElement) { - const { scrollHeight, scrollTop, clientHeight } = containerRefElement; - //once the user has scrolled within 500px of the bottom of the table, fetch more data if we can - if ( - scrollHeight - scrollTop - clientHeight < 500 && - !isFetching - ) { - fetchNextPage(); - } - } + //Infinite scrolling + const { _data, fetchNextPage, isFetching } = + useInfiniteQuery({ + queryKey: ['logs'], + queryFn: async () => { + const fetchedData = await loadNextPage(); + return fetchedData; }, - [fetchNextPage, isFetching, totalFetched, totalDBRowCount] - ); + initialPageParam: 0, + getNextPageParam: (_lastGroup, groups) => groups.length, + refetchOnWindowFocus: false, + placeholderData: keepPreviousData, + }); - //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data - React.useEffect(() => { - fetchMoreOnBottomReached(tableRef.current); - }, [fetchMoreOnBottomReached]); - } + flatData = _data || []; + totalFetched = flatData.length; + + //called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table + fetchMoreOnBottomReached = React.useCallback( + (containerRefElement = HTMLDivElement | null) => { + if (containerRefElement) { + const { scrollHeight, scrollTop, clientHeight } = containerRefElement; + //once the user has scrolled within 500px of the bottom of the table, fetch more data if we can + if ( + scrollHeight - scrollTop - clientHeight < 500 && + !isFetching + ) { + fetchNextPage(); + } + } + }, + [fetchNextPage, isFetching, totalFetched, totalDBRowCount] + ); + + //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data + React.useEffect(() => { + fetchMoreOnBottomReached(tableRef.current); + }, [fetchMoreOnBottomReached]); const table = useReactTable({ columns: finalColumns,