public inbox for [email protected]
help / color / mirror / Atom feedFrom: Pradip Parkale <[email protected]>
To: Akshay Joshi <[email protected]>
Cc: Aditya Toshniwal <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin][RM-7132]: Port Properties collection, Dashboard and SQL panel in React
Date: Mon, 4 Apr 2022 17:35:28 +0530
Message-ID: <CAJ9T6SvEMZREgf1qcrNfC9o+3RQsaL6xbZa5VTBwSmP6cBwywA@mail.gmail.com> (raw)
In-Reply-To: <CANxoLDdqFBoXw2jpQv7YseXHfzbzpG6WrStb+qn89HhVA=S3Gg@mail.gmail.com>
References: <CAJ9T6SsL-tzYYchh2KghWkHTY6y4L0=qCJ9VoGVCuu1WyT-0vQ@mail.gmail.com>
<CANxoLDdOUwHyUJ=-pDS94B9nX+5pRw3vZDQfMxHR-dH3d4c0CA@mail.gmail.com>
<CAM9w-_mnm_gk_03xONOCY7WaXmQMnww1NieuO4-KmvaFFPQRGA@mail.gmail.com>
<CAJ9T6StZWvdd1xkodyD3nLEL4ye+Z=sXQP06wzp7fc=DsX19dQ@mail.gmail.com>
<CAJ9T6Svt7hdfC5R444NdF_taL-2tQipVoMm1MuhvTus+rgopFA@mail.gmail.com>
<CAJ9T6SvZFeiXXfDn=Tp7tb9USiSFCZje0q3txjwrgSb6pPL_WA@mail.gmail.com>
<CANxoLDce0k6o-pg-2vZHwEwTSzJ89-cwG1gE=ce9QpnRFo5iJg@mail.gmail.com>
<CAJ9T6SsN6MHBv85L2GxNrrNc38XmkezpV8uUSXXYwQs5c9B1Sw@mail.gmail.com>
<CANxoLDdqFBoXw2jpQv7YseXHfzbzpG6WrStb+qn89HhVA=S3Gg@mail.gmail.com>
Hi Akshay,
Please find an updated patch. I have fixed the issue found in the testing.
On Wed, Mar 30, 2022 at 12:08 PM Akshay Joshi <[email protected]>
wrote:
> Thanks, the patch applied.
>
> On Wed, Mar 30, 2022 at 11:31 AM Pradip Parkale <
> [email protected]> wrote:
>
>> Hi Akhay,
>>
>> Please find the updated patch.I have fixed all the issues.
>>
>> On Mon, Mar 28, 2022 at 11:58 AM Akshay Joshi <
>> [email protected]> wrote:
>>
>>> Hi Pradip
>>>
>>> Following are the review comments (GUI):
>>>
>>> - Catalog objects should not be drop or drop cascade. Remove
>>> checkboxes from the properties panel.
>>> - Database column should be there for the 'Server Activity' table
>>> all tabs when the server is selected. When the database is selected it
>>> should be hidden.
>>> - Rename 'Lock' tab to 'Locks'.
>>> - Remove extra column 'Waiting' which was not there originally.
>>> - 'Server Activity' -> Sessions-> Details for the last record is not
>>> readable. Fix the scroll bar issue. Same with the Configuration tab last
>>> 4-5 records are not readable.
>>> - Select and expand the first and second records, the rest of the
>>> records are not visible, again seems to be a scroll bar issue.
>>> - 'Server Activity' -> Locks, "Granted?" column is empty, not
>>> showing any value.
>>> - Set the width of the column appropriately for all the tabs, for
>>> example, unit columns (in Configuration tab) width should be less, so that
>>> data on the other columns are more readable. Check all the tabs and set
>>> them appropriately
>>> - Faced "Request failed with status code 404" error. Select database
>>> server from browser tree and then select 'Server Activity'
>>> -> Configuration. Now select any database, you will get the error.
>>> - Properties panel size of the column having checkboxes should be
>>> less, compare with existing behavior.
>>> - Properties panel should show the message '*No Properties are
>>> available for the selected object*' if the respective collection
>>> node does not have children.
>>>
>>>
>>>
>>> On Mon, Mar 28, 2022 at 10:08 AM Pradip Parkale <
>>> [email protected]> wrote:
>>>
>>>> Hi,
>>>> Here is the updated patch. This patch includes the fix for #7215
>>>> <https://redmine.postgresql.org/issues/7215;.
>>>>
>>>> On Mon, Mar 28, 2022 at 9:11 AM Pradip Parkale <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi Aditya,
>>>>> Please ignore the previous email, find the updated patch attached.
>>>>>
>>>>> On Sun, Mar 27, 2022 at 11:07 PM Pradip Parkale <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Hi Aditya,
>>>>>> Please find the updated patch.
>>>>>>
>>>>>> On Tue, Mar 15, 2022 at 5:40 PM Aditya Toshniwal <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Hi Pradip,
>>>>>>>
>>>>>>> I did some basic usage and review and found below issues:
>>>>>>> 1. The code fails if you refresh the page and go to properties, when
>>>>>>> no node is selected.
>>>>>>> 2. I found below UI issues on selecting a database node. Also,
>>>>>>> checkbox column is too wide.
>>>>>>> [image: image.png]
>>>>>>> 3. Why is this in the node.js file. It should be in node_view.jsx.
>>>>>>>
>>>>>>> +
>>>>>>>
>>>>>>> + ReactDOM.render(
>>>>>>>
>>>>>>> + <Theme>
>>>>>>>
>>>>>>> + <CollectionNodeView
>>>>>>>
>>>>>>> + node={node}
>>>>>>>
>>>>>>> + treeNodeInfo={treeNodeInfo}
>>>>>>>
>>>>>>> + item={item}
>>>>>>>
>>>>>>> + itemNodeData={d}
>>>>>>>
>>>>>>> + pgBrowser={pgBrowser}
>>>>>>>
>>>>>>> + ></CollectionNodeView>
>>>>>>>
>>>>>>> + </Theme>,
>>>>>>>
>>>>>>> + b.panels['properties'].panel.$container[0]
>>>>>>>
>>>>>>> + );
>>>>>>>
>>>>>>> 4. I have seen a lot of commented codes. Few samples:
>>>>>>>
>>>>>>> + // if (that.canHide) {
>>>>>>>
>>>>>>>
>>>>>>> + //
>>>>>>> pgBrowser.Events.off('pgadmin-browser:tree:selected', () => {
>>>>>>>
>>>>>>> +
>>>>>>>
>>>>>>> + // removePanelView($container[0]);
>>>>>>>
>>>>>>> + // });
>>>>>>>
>>>>>>> 5. In WelcomeDashboard.jsx, the complete SVG code is put. Please
>>>>>>> move it to a file and import it.
>>>>>>> 6. Cleanup web/pgadmin/dashboard/static/js/dashboardDummy.js
>>>>>>> 7. Cleanup web/pgadmin/dashboard/static/js/dashboard_ponents.jsx
>>>>>>> 8. Rename Sql.jsx to SQL.jsx
>>>>>>> 9. The search is not working. It filters all.
>>>>>>> 10. If there is huge data then it should show some spinner.
>>>>>>> 11. Delete buttons should be disabled if no object is selected.
>>>>>>> 12. Delete buttons and search box should be on the same line.
>>>>>>>
>>>>>>> On Tue, Mar 15, 2022 at 4:01 PM Akshay Joshi <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Hi Aditya
>>>>>>>>
>>>>>>>> Can you please review/test it?
>>>>>>>>
>>>>>>>> On Mon, Mar 14, 2022 at 7:17 PM Pradip Parkale <
>>>>>>>> [email protected]> wrote:
>>>>>>>>
>>>>>>>>> Hi Hackers,
>>>>>>>>>
>>>>>>>>> Please find the attached patch for #7132
>>>>>>>>> <https://redmine.postgresql.org/issues/7132; Port Properties
>>>>>>>>> collection, Dashboard and SQL panel in React.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Thanks & Regards,
>>>>>>>>> Pradip Parkale
>>>>>>>>> Software Engineer | EnterpriseDB Corporation
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> *Thanks & Regards*
>>>>>>>> *Akshay Joshi*
>>>>>>>> *pgAdmin Hacker | Principal Software Architect*
>>>>>>>> *EDB Postgres <http://edbpostgres.com>*
>>>>>>>>
>>>>>>>> *Mobile: +91 976-788-8246*
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Thanks,
>>>>>>> Aditya Toshniwal
>>>>>>> pgAdmin Hacker | Software Architect | *edbpostgres.com*
>>>>>>> <http://edbpostgres.com;
>>>>>>> "Don't Complain about Heat, Plant a TREE"
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Thanks & Regards,
>>>>>> Pradip Parkale
>>>>>> Software Engineer | EnterpriseDB Corporation
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Thanks & Regards,
>>>>> Pradip Parkale
>>>>> Software Engineer | EnterpriseDB Corporation
>>>>>
>>>>
>>>>
>>>> --
>>>> Thanks & Regards,
>>>> Pradip Parkale
>>>> Software Engineer | EnterpriseDB Corporation
>>>>
>>>
>>>
>>> --
>>> *Thanks & Regards*
>>> *Akshay Joshi*
>>> *pgAdmin Hacker | Principal Software Architect*
>>> *EDB Postgres <http://edbpostgres.com>*
>>>
>>> *Mobile: +91 976-788-8246*
>>>
>>
>>
>> --
>> Thanks & Regards,
>> Pradip Parkale
>> Software Engineer | EnterpriseDB Corporation
>>
>
>
> --
> *Thanks & Regards*
> *Akshay Joshi*
> *pgAdmin Hacker | Principal Software Architect*
> *EDB Postgres <http://edbpostgres.com>*
>
> *Mobile: +91 976-788-8246*
>
--
Thanks & Regards,
Pradip Parkale
Software Engineer | EnterpriseDB Corporation
Attachments:
[image/png] image.png (249.1K, 3-image.png)
download | view image
[application/octet-stream] RM7132_v8.patch (27.5K, 4-RM7132_v8.patch)
download | inline diff:
diff --git a/web/package.json b/web/package.json
index 2379e9188..d708b05e4 100644
--- a/web/package.json
+++ b/web/package.json
@@ -82,11 +82,6 @@
"@date-io/core": "^1.3.6",
"@date-io/date-fns": "1.x",
"@emotion/sheet": "^1.0.1",
- "@fortawesome/fontawesome-free": "^5.14.0",
- "@fortawesome/fontawesome-svg-core": "^6.1.0",
- "@fortawesome/free-regular-svg-icons": "^6.1.0",
- "@fortawesome/free-solid-svg-icons": "^6.1.0",
- "@fortawesome/react-fontawesome": "^0.1.18",
"@material-ui/core": "4.11.0",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "4.0.0-alpha.58",
@@ -128,7 +123,6 @@
"date-fns": "^2.24.0",
"diff-arrays-of-objects": "^1.1.8",
"dropzone": "^5.9.3",
- "html-loader": "^3.1.0",
"html2canvas": "^1.0.0-rc.7",
"immutability-helper": "^3.0.0",
"imports-loader": "^2.0.0",
@@ -162,7 +156,6 @@
"react-dom": "^17.0.1",
"react-draggable": "^4.4.4",
"react-rnd": "^10.3.5",
- "react-fontawesome": "^1.7.1",
"react-router-dom": "^6.2.2",
"react-select": "^4.2.1",
"react-table": "^7.6.3",
diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js
index 82001e107..167575d2c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js
@@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
-import { getNodeAjaxOptions,getNodeListByName } from '../../../../../../static/js/node_ajax';
+import { getNodeAjaxOptions, getNodeListByName } from '../../../../../../static/js/node_ajax';
import ExtensionsSchema from './extension.ui';
define('pgadmin.node.extension', [
@@ -98,7 +98,8 @@ define('pgadmin.node.extension', [
getSchema: (treeNodeInfo, itemNodeData)=>{
let nodeObj = pgAdmin.Browser.Nodes['extension'];
return new ExtensionsSchema(
- {
+ {
+ role:()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
extensionsList:()=>getNodeAjaxOptions('avails', nodeObj, treeNodeInfo, itemNodeData, { cacheLevel: 'server'},
(data)=>{
let res = [];
diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js
index 918faee7f..b0fcc6bd3 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js
@@ -24,11 +24,13 @@ export default class ExtensionsSchema extends BaseUISchema {
});
fieldOptions = {
extensionsList: [],
+ role:[],
schemaList: [],
...fieldOptions,
};
this.extensionsList = fieldOptions.extensionsList;
this.schemaList = fieldOptions.schemaList;
+ this.role = fieldOptions.role;
}
get idAttribute() {
@@ -89,6 +91,12 @@ export default class ExtensionsSchema extends BaseUISchema {
id: 'oid', label: gettext('OID'), type: 'text',
mode: ['properties'],
},
+ {
+ id: 'owner', label: gettext('Owner'),
+ options: this.role,
+ type: 'select',
+ mode: ['properties'], controlProps: { allowClear: false},
+ },
{
id: 'schema', label: gettext('Schema'), type: 'select',
mode: ['properties', 'create', 'edit'], group: gettext('Definition'),
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js
index 3a2bb65a8..576220638 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js
@@ -24,6 +24,7 @@ define('pgadmin.node.operator', [
columns: ['name', 'owner', 'description'],
canDrop: false,
canDropCascade: false,
+ canSelect: false
});
}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
index b360c6b8d..93944e3b9 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
@@ -29,7 +29,7 @@ function(
label: gettext('Partitions'),
type: 'coll-partition',
columns: [
- 'name', 'schema', 'partition_value', 'is_partitioned', 'description',
+ 'name', 'schema', 'partition_scheme', 'partition_value', 'is_partitioned', 'description',
],
canDrop: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
canDropCascade: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js
index 240665432..78760632d 100644
--- a/web/pgadmin/browser/static/js/collection.js
+++ b/web/pgadmin/browser/static/js/collection.js
@@ -6,9 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
-
-// import {removeNodeView} from './node_view';
-// import Notify from '../../../static/js/helpers/Notifier';
import {getPanelView} from './panel_view';
define([
@@ -92,11 +89,10 @@ define([
canDropCascade: true,
selectParentNodeOnDelete: false,
showProperties: function(item, data, panel) {
-
- let container = panel.$container[0];
+ let container = panel.$container.find('.obj_properties').first();
getPanelView(
pgBrowser.tree,
- container,
+ container[0],
pgBrowser,
panel._type
);
diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js
index 21ae4c06d..9e5244b7b 100644
--- a/web/pgadmin/browser/static/js/node.js
+++ b/web/pgadmin/browser/static/js/node.js
@@ -1261,16 +1261,11 @@ define('pgadmin.browser.node', [
$(this).data('node-prop', treeHierarchy);
/* Remove any dom rendered by getNodeView */
- removeNodeView(pgBrowser.panels['properties'].panel.$container[0]);
-
- var containerProperties = pgBrowser.panels['properties'].panel.$container;
- containerProperties.addClass('pg-panel-content pg-no-overflow pg-el-container');
-
-
+ removeNodeView(j[0]);
if(that.getSchema) {
let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
getNodeView(
- that.type, treeNodeInfo, 'properties', data, 'tab', containerProperties[0], this, onEdit
+ that.type, treeNodeInfo, 'properties', data, 'tab', j[0], this, onEdit
);
return;
}
diff --git a/web/pgadmin/browser/static/js/panel.js b/web/pgadmin/browser/static/js/panel.js
index c0bd9178f..cb30580a9 100644
--- a/web/pgadmin/browser/static/js/panel.js
+++ b/web/pgadmin/browser/static/js/panel.js
@@ -122,8 +122,6 @@ define(
that.resizedContainer.apply(myPanel);
}
-
-
if (myPanel._type == 'dashboard') {
getPanelView(
pgBrowser.tree,
@@ -150,7 +148,7 @@ define(
pgBrowser.Events.on('pgadmin-browser:tree:selected', () => {
- if(myPanel.isVisible()) {
+ if(myPanel.isVisible() && myPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
@@ -162,7 +160,7 @@ define(
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', () => {
- if(myPanel.isVisible()) {
+ if(myPanel.isVisible() && myPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
@@ -177,7 +175,6 @@ define(
},
eventFunc: function(eventName) {
var name = $(this).data('pgAdminName');
-
try {
pgBrowser.Events.trigger(
'pgadmin-browser:panel', eventName, this, arguments
@@ -244,10 +241,11 @@ define(
.scene()
.find('.pg-panel-content');
- if (isPanelVisible) {
+ if (isPanelVisible && selectedPanel._type !== 'properties') {
if (eventName == 'panelClosed') {
removePanelView($container[0]);
- } else if (eventName == 'panelVisibilityChanged') {
+ }
+ else if (eventName == 'panelVisibilityChanged' && selectedPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
diff --git a/web/pgadmin/browser/static/js/panel_view.jsx b/web/pgadmin/browser/static/js/panel_view.jsx
index 39122755d..f212debbf 100644
--- a/web/pgadmin/browser/static/js/panel_view.jsx
+++ b/web/pgadmin/browser/static/js/panel_view.jsx
@@ -53,8 +53,6 @@ export function getPanelView(
container
);
}
-
-
if (panelType == 'statistics') {
ReactDOM.render(
<Theme>
@@ -69,7 +67,7 @@ export function getPanelView(
container
);
}
- if (panelType == 'properties') {
+ if (panelType == 'properties' && nodeData?.is_collection) {
ReactDOM.render(
<Theme>
<CollectionNodeView
diff --git a/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js b/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js
index 69080e47d..a1450df7b 100644
--- a/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js
+++ b/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js
@@ -17,7 +17,7 @@ export default class ActiveQuery extends BaseUISchema {
});
}
-
+
get baseFields() {
return [
@@ -26,7 +26,7 @@ export default class ActiveQuery extends BaseUISchema {
label: gettext('Backend type'),
type: 'text',
editable: true,
- noEmpty: true,
+ noEmpty: false,
readonly: true,
mode: ['properties'],
group: gettext('Details'),
diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx
index 9c008b3cb..637f6cde4 100644
--- a/web/pgadmin/dashboard/static/js/Dashboard.jsx
+++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx
@@ -25,6 +25,7 @@ import ArrowDropDownOutlinedIcon from '@mui/icons-material/ArrowDropDownOutlined
import WelcomeDashboard from './WelcomeDashboard';
import ActiveQuery from './ActiveQuery.ui';
import _ from 'lodash';
+import CachedIcon from '@mui/icons-material/Cached';
function parseData(data) {
var res = [];
@@ -86,13 +87,25 @@ const useStyles = makeStyles((theme) => ({
...theme.mixins.panelBorder,
flexDirection: 'column',
overflow: 'hidden !important',
- flexGrow: 1
+ flexGrow: 1,
+ minWidth: '300px',
+ minHeight: '300px'
+ },
+ arrowButton: {
+ fontSize: '2rem !important',
+ margin: '-7px'
},
terminateButton: {
color: theme.palette.error.main
},
buttonClick: {
backgroundColor: theme.palette.grey[400]
+ },
+ refreshButton: {
+ marginLeft: 'auto',
+ height: '1.9rem',
+ width: '2.2rem',
+ ...theme.mixins.panelBorder,
}
}));
@@ -114,6 +127,7 @@ export default function Dashboard({
const [msg, setMsg] = useState('');
const[infoMsg, setInfo] = useState('');
const [val, setVal] = useState(0);
+ const [refresh, setRefresh] = useState();
const [schemaDict, setSchemaDict] = React.useState({});
if (!did) {
@@ -145,7 +159,7 @@ export default function Dashboard({
},
{
accessor: 'setting',
- Header: gettext('Setting'),
+ Header: gettext('Value'),
sortble: true,
resizable: true,
disableGlobalFilter: false,
@@ -273,7 +287,7 @@ export default function Dashboard({
<PgIconButton
size="xs"
noBorder
- icon={<SquareIcon fontSize="small" />}
+ icon={<SquareIcon/>}
onClick={() => {
if (!canTakeAction(row, 'cancel'))
return;
@@ -328,12 +342,11 @@ export default function Dashboard({
className={row.isExpanded ?classes.buttonClick : ''}
icon={
row.isExpanded ? (
- <ArrowDropDownOutlinedIcon />
+ <ArrowDropDownOutlinedIcon className={classes.arrowButton}/>
) : (
- <ArrowRightOutlinedIcon />
+ <ArrowRightOutlinedIcon className={classes.arrowButton}/>
)
}
- size="xs"
noBorder
onClick={(e) => {
e.preventDefault();
@@ -753,7 +766,28 @@ export default function Dashboard({
if (message != '') {
setMsg(message);
}
- }, [nodeData, val, did, preferences, infoMsg]);
+ return () => {
+ setRefresh();
+ };
+ }, [nodeData, val, did, preferences, infoMsg, refresh]);
+
+ const RefreshButton = () =>{
+ return(
+ <PgIconButton
+ size="xs"
+ noBorder
+ className={classes.refreshButton}
+ icon={<CachedIcon />}
+ onClick={(e) => {
+ e.preventDefault();
+ setRefresh(true);
+ }}
+ color="default"
+ aria-label="Refresh"
+ title={gettext('Refresh')}
+ ></PgIconButton>
+ );
+ };
return (
<>
@@ -783,6 +817,7 @@ export default function Dashboard({
{tab.map((tabValue, i) => {
return <Tab key={i} label={tabValue} />;
})}
+ <RefreshButton/>
</Tabs>
<PgTable
diff --git a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
index ccb605d67..b2aec80a7 100644
--- a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
+++ b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
@@ -142,6 +142,7 @@ export default function Dependencies({ nodeData, item, node, ...props }) {
}
if (message != '') {
setMsg(message);
+ setLoaderText('');
}
return () => {
setTableData([]);
diff --git a/web/pgadmin/misc/dependents/static/js/Dependents.jsx b/web/pgadmin/misc/dependents/static/js/Dependents.jsx
index 867368b97..6b66e1c50 100644
--- a/web/pgadmin/misc/dependents/static/js/Dependents.jsx
+++ b/web/pgadmin/misc/dependents/static/js/Dependents.jsx
@@ -141,13 +141,14 @@ export default function Dependents({ nodeData, item, node, ...props }) {
}
}
if (message != '') {
+ setLoaderText('');
setMsg(message);
}
return () => {
setTableData([]);
};
- }, [nodeData]);
+ }, [nodeData, item]);
return (
<>
@@ -162,7 +163,6 @@ export default function Dependents({ nodeData, item, node, ...props }) {
) : (
<div className={classes.emptyPanel}>
{loaderText ? (<Loader message={loaderText} className={classes.loading} />) :
-
<div className={classes.panelIcon}>
<i className="fa fa-exclamation-circle"></i>
<span className={classes.panelMessage}>{gettext(msg)}</span>
diff --git a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
index db20331a9..e8a042b36 100644
--- a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
+++ b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
@@ -19,6 +19,8 @@ import PgTable from 'sources/components/PgTable';
import Theme from 'sources/Theme';
import PropTypes from 'prop-types';
import { PgIconButton } from '../../static/js/components/Buttons';
+import DeleteIcon from '@material-ui/icons/Delete';
+import DeleteSweepIcon from '@material-ui/icons/DeleteSweep';
const useStyles = makeStyles((theme) => ({
emptyPanel: {
@@ -155,24 +157,13 @@ export function CollectionNodeView({
.then(function (res) {
if (res.success == 0) {
pgBrowser.report_error(res.errormsg, res.info);
- } else {
- pgBrowser.Events.trigger(
- 'pgadmin:browser:tree:refresh',
- selItem || pgBrowser.tree.selected(),
- {
- success: function () {
- pgBrowser.tree.select(selItem);
- selNode.callbacks.selected.apply(selNode, [selItem]);
- },
- }
- );
}
setReload(true);
})
.catch(function (error) {
- Notify.error(
+ Notify.alert(
gettext('Error dropping %s', selectedItemData._label.toLowerCase()),
- error.message
+ error.response.data.errormsg
);
});
};
@@ -190,7 +181,6 @@ export function CollectionNodeView({
let nodeObj =
pgAdmin.Browser.Nodes[itemNodeData?._type.replace('coll-', '')];
- let schema = nodeObj.getSchema.call(nodeObj, treeNodeInfo, itemNodeData);
let url = generateCollectionURL.call(nodeObj, item, 'properties');
const api = getApiInstance();
@@ -198,7 +188,8 @@ export function CollectionNodeView({
let tableColumns = [];
var column = {};
- if (itemNodeData._type.indexOf('coll-') > -1) {
+ if (itemNodeData._type.indexOf('coll-') > -1 && !_.isUndefined(nodeObj.getSchema)) {
+ let schema = nodeObj.getSchema?.call(nodeObj, treeNodeInfo, itemNodeData);
schema.fields.forEach((field) => {
if (node.columns.indexOf(field.id) > -1) {
if (field.label.indexOf('?') > -1) {
@@ -208,6 +199,7 @@ export function CollectionNodeView({
sortble: true,
resizable: false,
disableGlobalFilter: false,
+ minWidth: 100,
// eslint-disable-next-line react/display-name
Cell: ({ value }) => {
return (<Switch color="primary" checked={value} className={classes.readOnlySwitch} value={value} readOnly title={String(value)} />);
@@ -220,30 +212,45 @@ export function CollectionNodeView({
sortble: true,
resizable: false,
disableGlobalFilter: false,
+ minWidth: 100,
};
}
tableColumns.push(column);
}
});
- api({
- url: url,
- type: 'GET',
- })
- .then((res) => {
- res.data.forEach((element) => {
- element['icon'] = '';
- });
- setPgTableColumns(tableColumns);
- setData(res.data);
- setInfoMsg('No properties are available for the selected object.');
- })
- .catch((err) => {
- Notify.alert(
- gettext('Failed to retrieve data from the server.'),
- gettext(err.message)
- );
- });
+ }else{
+ node.columns.forEach((field) => {
+ column = {
+ Header: field,
+ accessor: field,
+ sortble: true,
+ resizable: false,
+ disableGlobalFilter: false,
+ minWidth: 100,
+ };
+ tableColumns.push(column);
+
+ });
}
+
+ api({
+ url: url,
+ type: 'GET',
+ })
+ .then((res) => {
+ res.data.forEach((element) => {
+ element['icon'] = '';
+ });
+ setPgTableColumns(tableColumns);
+ setData(res.data);
+ setInfoMsg('No properties are available for the selected object.');
+ })
+ .catch((err) => {
+ Notify.alert(
+ gettext('Failed to retrieve data from the server.'),
+ gettext(err.message)
+ );
+ });
}
}, [itemNodeData, node, item, reload]);
@@ -252,8 +259,8 @@ export function CollectionNodeView({
<Box >
<PgIconButton
className={classes.dropButton}
- variant="outlined"
- icon={<i className='fa fa-trash-alt delete_multiple' aria-hidden="true" role="img"></i>}
+
+ icon={<DeleteIcon/>}
aria-label="Delete/Drop"
title={gettext('Delete/Drop')}
onClick={() => {
@@ -267,8 +274,7 @@ export function CollectionNodeView({
></PgIconButton>
<PgIconButton
className={classes.dropButton}
- variant="outlined"
- icon={<i className='pg-font-icon icon-drop_cascade delete_multiple_cascade' aria-hidden="true" role="img"></i>}
+ icon={<DeleteSweepIcon />}
aria-label="Drop Cascade"
title={gettext('Drop Cascade')}
onClick={() => {
@@ -284,12 +290,12 @@ export function CollectionNodeView({
};
return (
- <Theme>
+ <Theme className='obj_properties'>
<Box className={classes.propertiesPanel}>
{data.length > 0 ?
(
<PgTable
- isSelectRow={!('catalog' in treeNodeInfo) && (itemNodeData.label !== 'Catalogs')}
+ isSelectRow={!('catalog' in treeNodeInfo) && (itemNodeData.label !== 'Catalogs') && _.isUndefined(node?.canSelect)}
customHeader={customHeader}
className={classes.autoResizer}
columns={pgTableColumns}
diff --git a/web/pgadmin/misc/statistics/static/js/Statistics.jsx b/web/pgadmin/misc/statistics/static/js/Statistics.jsx
index 305262680..c567b1e8d 100644
--- a/web/pgadmin/misc/statistics/static/js/Statistics.jsx
+++ b/web/pgadmin/misc/statistics/static/js/Statistics.jsx
@@ -206,6 +206,7 @@ export default function Statistics({ nodeData, item, node, ...props }) {
}
if (message != '') {
setMsg(message);
+ setLoaderText('');
}
return () => {
setTableData([]);
diff --git a/web/pgadmin/static/js/components/PgTable.jsx b/web/pgadmin/static/js/components/PgTable.jsx
index b6f9d12cb..265d833f3 100644
--- a/web/pgadmin/static/js/components/PgTable.jsx
+++ b/web/pgadmin/static/js/components/PgTable.jsx
@@ -47,7 +47,7 @@ const useStyles = makeStyles((theme) => ({
overflow: 'overlay !important',
},
customHeader:{
- marginTop: '12px',
+ marginTop: '8px',
marginLeft: '4px'
},
searchBox: {
@@ -55,6 +55,13 @@ const useStyles = makeStyles((theme) => ({
display: 'flex',
background: theme.palette.background.default
},
+ warning: {
+ backgroundColor: theme.palette.warning.main + '!important'
+ },
+ alert: {
+ backgroundColor: theme.palette.error.main + '!important'
+ },
+
tableContentWidth: {
width: 'calc(100% - 3px)',
},
@@ -105,10 +112,11 @@ const useStyles = makeStyles((theme) => ({
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
backgroundColor: theme.otherVars.tableBg,
+ userSelect: 'text'
},
selectCell: {
textAlign: 'center',
- minWidth: '25px'
+ minWidth: 20
},
tableCellHeader: {
fontWeight: theme.typography.fontWeightBold,
@@ -177,6 +185,10 @@ export default function PgTable({ columns, data, isSelectRow, offset=105, ...pro
const rowHeights = React.useRef({});
const rowRef = React.useRef({});
+ // Reset Search vakue in tab changed.
+ React.useEffect(()=>{
+ setSearchVal('');
+ },[columns]);
function getRowHeight(index, size) {
return rowHeights.current[index] + size || 35;
}
@@ -257,21 +269,49 @@ export default function PgTable({ columns, data, isSelectRow, offset=105, ...pro
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
- Header: ({ getToggleAllRowsSelectedProps }) => (
- <div className={classes.selectCell}>
- <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
- </div>
- ),
+ Header: ({ getToggleAllRowsSelectedProps, toggleRowSelected, isAllRowsSelected, rows }) => {
+
+ const modifiedOnChange = (event) => {
+ rows.forEach((row) => {
+ //check each row if it is not disabled
+ !(!_.isUndefined(row.original.canDrop) && !(row.original.canDrop)) && toggleRowSelected(row.id, event.currentTarget.checked);
+
+ });
+ };
+
+ let allTableRows = 0;
+ let selectedTableRows = 0;
+ rows.forEach((row) => {
+ row.isSelected && selectedTableRows++;
+ (_.isUndefined(row.original.canDrop) || row.original.canDrop) && allTableRows++;
+ });
+ const disabled = allTableRows === 0;
+ const checked =
+ (isAllRowsSelected ||
+ allTableRows === selectedTableRows) &&
+ !disabled;
+ return(
+ <div className={classes.selectCell}>
+ <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()
+ }
+ onChange={modifiedOnChange}
+ checked={checked}
+ />
+ </div>
+ );},
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div className={classes.selectCell}>
- <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
+ <IndeterminateCheckbox {...row.getToggleRowSelectedProps()}
+ disabled={!_.isUndefined(row.original.canDrop) ? !(row.original.canDrop) : false}
+ />
</div>
),
sortble: false,
width: 30,
- minWidth: 0,
+ maxWidth: 30,
+ minWidth: 0
},
...CLOUMNS,
];
@@ -337,8 +377,15 @@ export default function PgTable({ columns, data, isSelectRow, offset=105, ...pro
if(cell.column.id == 'btn-edit' && row.isExpanded) {
classNames.push(classes.expandedIconCell);
}
+ if (row.original.row_type === 'warning'){
+ classNames.push(classes.warning);
+ }
+ if (row.original.row_type === 'alert'){
+ classNames.push(classes.alert);
+ }
return (
- <div key={cell.column.id} {...cell.getCellProps()} className={clsx(classNames, row.original.icon && row.original.icon[cell.column.id], row.original.icon[cell.column.id] && classes.cellIcon)} title={String(cell.value)}>
+ <div key={cell.column.id} {...cell.getCellProps()} className={clsx(classNames, row.original.icon && row.original.icon[cell.column.id], row.original.icon[cell.column.id] && classes.cellIcon)}
+ title={_.isUndefined(cell.value) || _.isNull(cell.value) ? '': String(cell.value)}>
{cell.render('Cell')}
</div>
);
@@ -467,14 +514,17 @@ PgTable.propTypes = {
PropTypes.node,
]),
getToggleAllRowsSelectedProps: PropTypes.func,
+ toggleRowSelected: PropTypes.func,
columns: PropTypes.array,
data: PropTypes.array,
isSelectRow: PropTypes.bool,
+ isAllRowsSelected: PropTypes.bool,
row: PropTypes.func,
setSelectedRows: PropTypes.func,
getSelectedRows: PropTypes.func,
searchText: PropTypes.string,
type: PropTypes.string,
sortOptions: PropTypes.array,
- schema: PropTypes.object
+ schema: PropTypes.object,
+ rows: PropTypes.object
};
view thread (10+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected]
Subject: Re: [pgAdmin][RM-7132]: Port Properties collection, Dashboard and SQL panel in React
In-Reply-To: <CAJ9T6SvEMZREgf1qcrNfC9o+3RQsaL6xbZa5VTBwSmP6cBwywA@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox