Compare commits

..
212 Commits
Author SHA1 Message Date
Aditya Toshniwal cda7d7de90 Fix a crash issue on RHEL based OS's occurring when File menu is clicked. 2024-08-20 16:33:12 +05:30
Aditya Toshniwal e7981c7f11 Fix windows, linux builds as pgAdmin 4 desktop is not opening. 2024-08-20 13:05:59 +05:30
Aditya Toshniwal ba87cbecfd Update release notes. 2024-08-19 15:17:24 +05:30
Akshay Joshi bf6b963c45 Update version for release v8.11 2024-08-19 15:09:49 +05:30
Libor M. 9f8acfc51d Czech translation for version 8.11 2024-08-19 15:07:19 +05:30
Ashesh Vashi 8cf316b853 Fixed some of the issues reported due to introduction of the custom hook 'useSchemaState'. #7776 2024-08-19 09:53:00 +05:30
Akshay Joshi 55817f685f Updated message catalogs for v8.11 2024-08-15 21:36:39 +05:30
Aditya Toshniwal 35d585251a Upgrade xterm realted packages to the latest @xterm based namespace. 2024-08-14 18:15:03 +05:30
Aditya Toshniwal 242dd48cbd Improve code highlighting in query editor. #7748 2024-08-14 16:48:51 +05:30
dependabot[bot] 30134800f3 Javascript dependency: Bump axios from 1.7.3 to 1.7.4 in /runtime (#7813)
Bumps [axios](https://github.com/axios/axios) from 1.7.3 to 1.7.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.3...v1.7.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-14 11:17:49 +05:30
dependabot[bot] e517fdf6bc Javascript dependency: Bump axios from 1.7.2 to 1.7.4 in /web (#7814)
Bumps [axios](https://github.com/axios/axios) from 1.7.2 to 1.7.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.2...v1.7.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-14 11:17:27 +05:30
Aditya Toshniwal b00ea3cd99 Update release notes. 2024-08-14 11:12:30 +05:30
Pravesh Sharma c0b6c8726e Add a home button to the geometry viewer to set original zoom level when the viewer was opened. #2046 2024-08-14 11:09:28 +05:30
Rohit Bhati 52c550e3fe Fix an issue where ERD tool should to be able to open saved pgerd file when using keyboard shortcuts. #7688 2024-08-13 14:30:58 +05:30
Aditya Toshniwal 57e72ce598 Fixed bugs found when testing react-data-grid upgrade changes. #7705 2024-08-13 13:00:52 +05:30
Aditya Toshniwal ba3deb5b9b Fixed paths for Flatpak broken after Electron changes. #7793 2024-08-12 13:32:58 +05:30
Khushboo Vashi fb0022923a Fix import Export Server loading issue, affected due to SchemaView component changes. 2024-08-12 11:27:21 +05:30
dependabot[bot] ccaea82341 Javascript dependency: Bump svgo from 2.8.0 to 3.3.2 in /web
Bumps [svgo](https://github.com/svg/svgo) from 2.8.0 to 3.3.2.
- [Release notes](https://github.com/svg/svgo/releases)
- [Commits](https://github.com/svg/svgo/compare/v2.8.0...v3.3.2)

---
updated-dependencies:
- dependency-name: svgo
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 11:23:30 +05:30
dependabot[bot] 1a143c9e2c Python dependency: Update setuptools requirement in /web/regression
Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v71.0.0...v72.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 17:19:46 +05:30
dependabot[bot] 23d15bde8b Python dependency: Update setuptools requirement from ==71.* to ==72.*
Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v71.0.0...v72.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 17:19:29 +05:30
dependabot[bot] 49c55b41a2 Javascript dependency: Bump @mui/icons-material in /web
Bumps [@mui/icons-material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material) from 5.16.5 to 5.16.6.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v5.16.6/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v5.16.6/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 17:18:50 +05:30
dependabot[bot] 4f822c8021 Javascript dependency: Bump @tanstack/react-virtual in /web
Bumps [@tanstack/react-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/react-virtual) from 3.8.3 to 3.8.4.
- [Release notes](https://github.com/TanStack/virtual/releases)
- [Commits](https://github.com/TanStack/virtual/commits/v3.8.4/packages/react-virtual)

---
updated-dependencies:
- dependency-name: "@tanstack/react-virtual"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 17:18:30 +05:30
Akshay Joshi c3801165a5 Set the yarn version for Wheel Package. 2024-08-08 15:01:27 +05:30
dependabot[bot] fdf58f2d85 Python dependency: Update keyring requirement in /web/regression
Updates the requirements on [keyring](https://github.com/jaraco/keyring) to permit the latest version.
- [Release notes](https://github.com/jaraco/keyring/releases)
- [Changelog](https://github.com/jaraco/keyring/blob/main/NEWS.rst)
- [Commits](https://github.com/jaraco/keyring/compare/v24.0.0...v25.2.1)

---
updated-dependencies:
- dependency-name: keyring
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:42:32 +05:30
dependabot[bot] 9a3b3530a6 Python dependency: Update keyring requirement from ==24.* to ==25.*
Updates the requirements on [keyring](https://github.com/jaraco/keyring) to permit the latest version.
- [Release notes](https://github.com/jaraco/keyring/releases)
- [Changelog](https://github.com/jaraco/keyring/blob/main/NEWS.rst)
- [Commits](https://github.com/jaraco/keyring/compare/v24.0.0...v25.2.1)

---
updated-dependencies:
- dependency-name: keyring
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:42:16 +05:30
dependabot[bot] b280c91013 Javascript dependency: Bump svgo-loader from 2.2.2 to 4.0.0 in /web
Bumps [svgo-loader](https://github.com/svg/svgo-loader) from 2.2.2 to 4.0.0.
- [Release notes](https://github.com/svg/svgo-loader/releases)
- [Commits](https://github.com/svg/svgo-loader/commits/v4.0.0)

---
updated-dependencies:
- dependency-name: svgo-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:19:48 +05:30
dependabot[bot] 95f6a63c70 Javascript dependency: Bump xterm-addon-search in /web (#7758)
Bumps [xterm-addon-search](https://github.com/xtermjs/xterm.js) from 0.8.2 to 0.13.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.13)

---
updated-dependencies:
- dependency-name: xterm-addon-search
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:14:22 +05:30
dependabot[bot] 96965797f6 Javascript dependency: Bump xterm from 4.19.0 to 5.3.0 in /web
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.19.0 to 5.3.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/4.19.0...5.3.0)

---
updated-dependencies:
- dependency-name: xterm
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:14:02 +05:30
dependabot[bot] 7b5d96c5a6 Javascript dependency: Bump axios from 1.7.2 to 1.7.3 in /runtime
Bumps [axios](https://github.com/axios/axios) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.2...v1.7.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 13:12:54 +05:30
Akshay Joshi 00e2480b7b 1) Fixed an issue where refreshing the Schema Diff tool opened in a new tab caused an error. #7499
2) Fixed an issue where the Generate Script ignored filter conditions when a parent node was selected. #7682
2024-08-08 13:02:38 +05:30
Khushboo Vashi f98e3fa1fd Update release note. 2024-08-07 14:50:55 +05:30
Rohit Bhati 81d8ea56f8 Fix server heartbeat logging error after deleting the server. #7540 2024-08-07 14:32:48 +05:30
Pravesh Sharma 654dc0e2d7 Fixed an issue where the value in the find box is not updating with selected text in editor if find is already open and re-triggered. #7775 2024-08-06 11:59:22 +05:30
Khushboo Vashi b4e4b9d498 Fix an issue where the wheel package is not getting installed on the arm64-based macOS version < 14. #7754 2024-08-05 12:31:28 +05:30
Ashesh Vashi 52af8d3e49 Introduce custom React Hook useSchemaState to simplify SchemaView component. #7776
Changes include: 
- Simplify current SchemaView code
- Add ability to reuse the schema data & state management implementation outside the SchemaDialogView component.
- Further split components in small and manageable separate files.
- Removed the 'DepListenerContext' context as there was no need for separate context.
- Added a reload functionality in the 'useSchemaState'
- Changes in feature tests.
2024-08-02 09:59:01 +05:30
Aditya Toshniwal 546806c40c Always use latest version of Electron in package.json and in builds 2024-08-01 16:03:05 +05:30
Aditya Toshniwal ca7e93cc2c Fix failing windows builds by using Yarn v3 2024-08-01 15:00:30 +05:30
Aditya Toshniwal 4ee76ba8c9 Build changes to sign pgAdmin4.exe and use yarn v3 on linux builds 2024-08-01 13:18:01 +05:30
Rohit Bhati 5d7ec14076 Fixed delete object(shortcut key) affecting both text and Object Explorer items. #7683 2024-08-01 11:48:16 +05:30
Akshay Joshi 88f033e2a8 Update release note 2024-08-01 11:38:23 +05:30
Pravesh Sharma 2e878a3fb2 Fixed an issue where the REVOKE statement in the create script was throwing an error if the role contained special characters. #7737 2024-08-01 11:34:00 +05:30
Aditya Toshniwal c6e7ce03cc Upgrade react-data-grid fork to latest and change pgAdmin accordingly. #7705 2024-07-31 19:12:36 +05:30
Kundan c45fb47b08 Make PgTreeView react component more customisable 2024-07-31 14:07:47 +05:30
Akshay Joshi d39fe78239 Added release note for v8.11 2024-07-31 11:34:29 +05:30
Pravesh Sharma 0399d0be15 Updated the documentation for web server authentication. #7728 2024-07-31 11:26:19 +05:30
Rohit Bhati 19237fe247 Fixed an issue where delete object(shortcut key) affecting both text and Object Explorer items. #7683 2024-07-31 11:25:08 +05:30
Akshay Joshi 729c370125 Fixed build issues after package upgrade. 2024-07-30 13:41:56 +05:30
Akshay Joshi 636c224bd0 Updated JavaScript and Python packages according to Dependabot recommendations 2024-07-29 19:34:43 +05:30
Aditya Toshniwal ab25238f17 Fix an issue where file dialog is not focussed on open in electron. 2024-07-29 10:18:39 +05:30
Khushboo Vashi b9ffbf73e0 Fixed an issue where only psycopg-binary should be installed but PIP wheel installing psycopg-c as well. 2024-07-29 10:16:42 +05:30
Aditya Toshniwal 23cad47f8d Fix a syntax error in postinst when installing Ubuntu 24 deb package 2024-07-25 19:26:12 +05:30
Aditya Toshniwal 5fd308aafc Show OS name and version details in about dialog for Linux platforms. 2024-07-25 17:51:31 +05:30
Aditya Toshniwal 88bee071e5 Make sure AppArmor profile is added only for Ubuntu 24 and above. 2024-07-25 17:27:18 +05:30
Khushboo Vashi 1fcb1f0228 Fix Dashboard UI issues. 2024-07-25 12:43:02 +05:30
Aditya Toshniwal 9544ce1d18 Add apparmor profile for pgAdmin when installing on Debian based OS 2024-07-25 11:40:19 +05:30
Akshay Joshi 8cf15ea17c Change the release date in the release note. 2024-07-24 15:47:42 +05:30
Khushboo Vashi bc10fa5c03 Fix an issue where a cloud instance deployment fails due to wrong import. 2024-07-24 15:34:30 +05:30
Aditya Toshniwal 1d5f5a2067 Fixed an issue where ERD Open/Save shorcuts were not working on Windows/Linux. #7639 2024-07-24 15:11:05 +05:30
jcodeio 70a7c42be1 Set the MFA OTP field to be a normal textbox to eliminate the save password prompt. 2024-07-24 15:00:27 +05:30
Khushboo Vashi d0e6090761 Fix Dashboard State refresh issue with the active sessions only. 2024-07-24 13:45:52 +05:30
Akshay Joshi 87ba177ff3 Fixed linter error. 2024-07-24 13:02:46 +05:30
Akshay Joshi 0511554db9 The following issues have been fixed:
1) White screen issue after closing the Macro dialog.
2) Schema Diff database and schema selection issue.
3) CSV download issue.
2024-07-24 12:54:20 +05:30
Aditya Toshniwal 026292f07b Fix tab focus issue when closing query tool using keyboard shortcut. #6572 2024-07-23 17:02:39 +05:30
Aditya Toshniwal 18d507780d Hide the 'Toggle Full Screen' menu on Linux as it hides the top menu completely making the app unable to use. #7494 2024-07-23 15:17:29 +05:30
Khushboo Vashi 3aedae1436 Call loadNextPage function only when it is required while loading the table. 2024-07-22 14:15:03 +05:30
Akshay Joshi 9cbb9a3d24 Update version for release 8.10 2024-07-22 11:34:28 +05:30
Rohit Bhati b173fda116 Fix tab focus issue while deleting multiple tabs using shortcut key. #6572 2024-07-22 11:32:26 +05:30
Libor M. d9ccef94a2 Czech translation for version 8.10 2024-07-22 11:20:35 +05:30
Akshay Joshi eff63931f2 Update message catalogs. 2024-07-19 15:23:19 +05:30
Pravesh Sharma 3ec676194b Fixed an issue where boolean values in node details of graphical explain plan were not interpreted correctly. #7662 2024-07-18 17:59:58 +05:30
Rohit Bhati 8030bc708b Add support for highlighting selection matches in the query editor. #7530 2024-07-18 17:51:20 +05:30
Khushboo Vashi fd78faf0cc Update release notes. 2024-07-18 14:30:45 +05:30
Pravesh Sharma bfcdcdc4f1 Add a precautionary check for the query tool connection cursor to fix the error 'NoneType' object has no attribute '_query'. #7660 2024-07-18 14:24:50 +05:30
Pravesh Sharma a75273a714 Updated entrypoint.sh to utilize the email-validator package for email validation. #7297 2024-07-18 11:05:37 +05:30
Khushboo Vashi c9cc5257c7 Fix Server Log minor UI issues. 2024-07-18 09:40:49 +05:30
Aditya Toshniwal 3b4fa40253 Update release notes. 2024-07-17 18:22:51 +05:30
Rohit Bhati 9ee896aac4 Add a keyboard shortcut to close active tab panel. #6572 2024-07-17 18:19:36 +05:30
Aditya Toshniwal 01cb1839f8 Fix git commit hash details for pip build. #7623
Skip regression folder when creating pip builds to reduce bundle size.
2024-07-17 14:30:02 +05:30
Yogesh Mahajan 1eb07608e9 Ensure processes related notifiers disappears. #7219 2024-07-17 13:07:52 +05:30
Aditya Toshniwal 8e16e000c3 Fix issues found in electron testing. #7494 2024-07-16 20:29:10 +05:30
Akshay Joshi 64d7c2c62d Update release notes. 2024-07-16 17:52:15 +05:30
Yogesh Mahajan e028ebc152 Ensure pgadmin does not try to connect to the server if saved password is not available. #7679 2024-07-16 17:46:40 +05:30
Anil Sahoo 30051f3257 Fixed an issue where Reassign/Drop Owned dialog not opening for Role. #7663 2024-07-16 17:42:16 +05:30
Yogesh Mahajan c4a52687b6 Ensure that pgAdmin works when opened in an iframe. #7681 2024-07-16 16:32:52 +05:30
Pravesh Sharma a06c13623d Fixed an issue where theme preview under theme options was broken in pgAdmin server mode. #7626 2024-07-16 10:25:48 +05:30
Khushboo Vashi b303693ae8 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.
2024-07-11 10:26:42 +05:30
Khushboo Vashi 6b012193e3 Pin Psycopg Binary packages to 3.1.19 for the ARM64 MacOS platform wheel packages. 2024-07-10 17:43:13 +05:30
Aditya Toshniwal cd6ff48cc0 Fix query tool, ERD closing issue in Electron. #7494 2024-07-10 15:01:35 +05:30
Aditya Toshniwal dbdea181a9 Fixed an issue where pop-up notifications from Object Explorer wouldn't get dismissed automatically if the Query Tool was opened. #6571 2024-07-09 16:25:04 +05:30
Rohit Bhati 721a5da895 Fixed an issue where Generate Script button should be disabled if no objects are selected in the schema diff result. #7638 2024-07-09 13:44:04 +05:30
Khushboo Vashi 8578acd915 Update release notes. 2024-07-09 12:57:48 +05:30
Pravesh Sharma f3c95d9643 Fix an issue where the preferences JSON file has no effect when an external database is used. #7618 2024-07-09 12:52:23 +05:30
Anil Sahoo 5c5b61c4db Fixed an issue where paste operation in query tool data grid should skip bytea columns and put the value as NULL instead. #3199 2024-07-09 10:33:29 +05:30
Aditya Toshniwal 760e38293c Fix issues found during Electron testing. #7494
Fix application crash when using users dialog. #7607
2024-07-08 19:24:29 +05:30
Aditya Toshniwal dcfef154ce - Set the browser target to ES6 and reduce the JS bundle size considerably
- Upgrade ESLint to v9.x and migrate the .eslintrc.js file to make it work
2024-07-04 18:25:47 +05:30
Pravesh Sharma 10b2e91e29 Update react-diagrams library which is used in ERD to the latest version. #7644
Added patch for DataGridView failing when adding a new row.
2024-07-03 18:19:27 +05:30
Khushboo Vashi 4f415f9768 Added support for viewing PostgreSQL Server Logs in Text, CSV and JSON formats. #3981 2024-07-03 16:17:29 +05:30
Akshay Joshi 93b5bc6bf8 Update release note. 2024-07-03 11:54:49 +05:30
Aditya Toshniwal 60c2d0e23b Update more JS packages. 2024-07-03 11:46:16 +05:30
dependabot[bot] c44710c9d7 Javascript dependency: Bump @eslint/js from 9.5.0 to 9.6.0 in /runtime (#7646)
Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.5.0 to 9.6.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.6.0/packages/js)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 11:49:44 +05:30
dependabot[bot] 37e034b3ef Python dependency: Bump psycopg[c] in /web/regression
Bumps [psycopg[c]](https://github.com/psycopg/psycopg) from 3.1.19 to 3.2.1.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.1.19...3.2.1)

---
updated-dependencies:
- dependency-name: psycopg[c]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 11:49:10 +05:30
dependabot[bot] adb8fdb096 Python dependency: Bump psycopg[c] from 3.1.19 to 3.2.1
Bumps [psycopg[c]](https://github.com/psycopg/psycopg) from 3.1.19 to 3.2.1.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.1.19...3.2.1)

---
updated-dependencies:
- dependency-name: psycopg[c]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 11:48:54 +05:30
Rohit Bhati 22cdb86aab Fix issue with missing new added records in download file. #5345 2024-07-02 11:48:13 +05:30
Akshay Joshi 576dc55615 Fixed the permission denied issue for functions of the pgstattuple extension when accessing statistics with a non-admin user. #7035 2024-07-02 11:47:43 +05:30
Aditya Toshniwal f8fa1cf6d6 - Fix few SonarQube issues.
- Cleanup NW.js related stuff.
2024-07-02 10:34:30 +05:30
Aditya Toshniwal 3bb9f0ba8c Remove support for Python 3.7 as Debian 10 is EOL. 2024-07-01 12:39:12 +05:30
Aditya Toshniwal 91eb60a363 Replace pgAdmin NW.js container with Electron container. #7494 2024-07-01 11:27:42 +05:30
Pravesh Sharma 4457a6a6a1 Updated to the latest version of the Notistack library. #7501 2024-07-01 11:26:45 +05:30
Akshay Joshi 6f8cde67a6 Update release note. 2024-06-28 15:09:34 +05:30
Pravesh Sharma 391db5131d Fixed an issue where sorting the database activity table on the dashboard by any column caused the details to expand in the wrong position. #7554 2024-06-28 14:47:26 +05:30
Pravesh Sharma 62a61b403e Fixed an issue where users could not autofill their saved passwords in the connect server dialog in the browser. #7627 2024-06-28 14:44:39 +05:30
Aditya Toshniwal e8f108154d Fix build failures. 2024-06-27 18:03:10 +05:30
Akshay Joshi ccd84b7c2a Update JS packages. 2024-06-27 14:08:01 +05:30
dependabot[bot] 522f3458f6 Python dependency: Update psutil requirement in /web/regression
Updates the requirements on [psutil](https://github.com/giampaolo/psutil) to permit the latest version.
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.0...release-6.0.0)

---
updated-dependencies:
- dependency-name: psutil
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 13:26:38 +05:30
dependabot[bot] 7efed95ac3 Python dependency: Update psutil requirement from ==5.9.* to ==6.0.*
Updates the requirements on [psutil](https://github.com/giampaolo/psutil) to permit the latest version.
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.0...release-6.0.0)

---
updated-dependencies:
- dependency-name: psutil
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 13:25:47 +05:30
dependabot[bot] 754cd223c1 Python dependency: Bump selenium in /web/regression
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.21.0 to 4.22.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.21.0...selenium-4.22.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 13:23:57 +05:30
dependabot[bot] a0b7dcca64 Python dependency: Bump azure-identity in /web/regression
Bumps [azure-identity](https://github.com/Azure/azure-sdk-for-python) from 1.16.1 to 1.17.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-identity_1.16.1...azure-identity_1.17.1)

---
updated-dependencies:
- dependency-name: azure-identity
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 13:23:39 +05:30
dependabot[bot] 8876183981 Python dependency: Bump azure-identity from 1.16.1 to 1.17.1
Bumps [azure-identity](https://github.com/Azure/azure-sdk-for-python) from 1.16.1 to 1.17.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-identity_1.16.1...azure-identity_1.17.1)

---
updated-dependencies:
- dependency-name: azure-identity
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 13:23:20 +05:30
Aditya Toshniwal feb3093c6d Automatically apply virtualization in the DataGridView of SchemaView if the schema contains only one collection. #7607 2024-06-27 13:21:18 +05:30
Aditya Toshniwal 6f96f67655 Add the git commit hash details to the About dialog. #7623 2024-06-27 13:20:00 +05:30
Akshay Joshi 3be2221948 Ensure that pgAdmin 4 is compatible with PostgreSQL v17. #7537 2024-06-27 13:18:26 +05:30
Akshay Joshi 7d0bbf30ec Fixed the issue causing the 2FA dialog to appear distorted. 2024-06-25 14:46:30 +05:30
Akshay Joshi 9933a9a9e5 Update version for release v8.9 2024-06-24 20:10:25 +05:30
Akshay Joshi 227f047810 Revert last commit as attr not working. 2024-06-24 19:08:33 +05:30
Khushboo Vashi 95ce9e976e Set the pgAdmin executable file permissions to 755 for the web rpm build. 2024-06-24 18:20:19 +05:30
Khushboo Vashi 4a645343a9 Give the proper file/directory permissions to the pgAdmin installation directory on RHEL-8. This is the only platform that has write permission for the executable files after installation which is fixed. 2024-06-24 17:09:28 +05:30
Khushboo Vashi 3d107ea618 One more attempt to set RHEL-8 file permissions. 2024-06-24 16:05:22 +05:30
Libor M 19f5e41b09 Czech translation for version 8.9 2024-06-24 11:55:52 +05:30
Khushboo Vashi f7eeefa3a9 Fix file permissions for RHEL 8. 2024-06-24 10:54:39 +05:30
Yogesh Mahajan a8f0f5bb4f Fix one more styling issue broken due to JSS changes. #7363 2024-06-24 10:44:05 +05:30
Aditya Toshniwal 44d40f0785 Fixed an issue where delete button in Users data was enabled for incorrect rows. #7616 2024-06-24 10:31:47 +05:30
Domenico Sgarbossa d0b2752fea Italian translation updated for v8.9 2024-06-21 13:14:48 +05:30
Akshay Joshi 8e0c080faf Update message catalogs for v8.9 2024-06-20 18:12:16 +05:30
Yogesh Mahajan 6410ae5f69 Fixed some more styling issues broken due to JSS changes. #7363 2024-06-20 17:18:38 +05:30
Khushboo Vashi a60cbf00c8 Do not change the file permission for the Redhat installation directory. 2024-06-20 17:11:23 +05:30
Akshay Joshi 3e7a220225 Fixed an issue where the schema diff incorrectly marked tables as different due to schema-qualified trigger functions in the trigger definitions. #7523 2024-06-20 16:55:38 +05:30
Aditya Toshniwal 9026f46220 Fixed an issue where object explorer toolbar button not showing shortcut in the tooltip.#7316 2024-06-20 11:31:11 +05:30
Yogesh Mahajan fedbe550db Optimise logic used for OS theme syncing. #5932 2024-06-20 11:05:47 +05:30
Khushboo Vashi 2b45a1f7d5 Fix Redhat installation directory permission. 2024-06-20 10:39:24 +05:30
Aditya Toshniwal 31a91409a0 Fixed incorrect sorting of size in statistics tab. #7542 2024-06-19 18:27:43 +05:30
Aditya Toshniwal 9279393dcd Add missing files from last commit. #7593 2024-06-19 17:57:34 +05:30
Aditya Toshniwal 20caa63508 Fixed an issue where query tool auto-complete stops working after connection change. #7593 2024-06-19 17:55:40 +05:30
Akshay Joshi 6984e97f8d Use correct for loop syntax. 2024-06-19 13:15:45 +05:30
Yogesh Mahajan 95ffd1b9a1 More fixes for issues reported while testing changes related to makeStyle JSS changes and auto-theme. #7363 2024-06-19 11:54:18 +05:30
Akshay Joshi 4c5639bee6 Correct the alignment. 2024-06-18 18:25:38 +05:30
Kolja d4b72e2d89 Detect if pgAdmin is running in Flatpak. 2024-06-18 18:22:13 +05:30
Akshay Joshi 0452828cc7 1) Change the cursor to a pointer for JSON editor toolbar buttons.
2) Remove the extra scrollbar in JSON editor.
3) Set the focus on the PSQL tool.
2024-06-18 16:42:17 +05:30
Aditya Toshniwal 007c4840c2 Fix failing feature tests 2024-06-18 14:02:23 +05:30
Akshay Joshi 2b04f3ca1d Fixed incorrect handling of the code smell for the reject API call 2024-06-17 18:22:38 +05:30
Anil Sahoo 3706c3126a Fixed migration failure while using external database. #7556 2024-06-17 18:12:31 +05:30
Rohit Bhati 1ba9f005a7 Ensure that user should be able to clear comments in RLS Policy. 2024-06-17 18:11:57 +05:30
Aditya Toshniwal c3d6f8887a Fixed an issue where syntax highlighting is incorrect for C-Style escape string. #7485 2024-06-17 17:05:36 +05:30
Aditya Toshniwal 439d6cb28f Fixed an issue where backslash breaks syntax highlighting. #7528 2024-06-17 16:16:15 +05:30
Yogesh Mahajan b0e7847962 Fixed bugs found while testing makeStyles JSS changes. #7363 2024-06-17 15:45:40 +05:30
Anil Sahoo a946c70869 Fixed an issue where changing a column name should reflect in all the constraints in table object dialog and ERD table dialog. #7476 2024-06-17 14:07:45 +05:30
Akshay Joshi 5866da8194 Fixed SonarQube code smells. 2024-06-13 18:48:02 +05:30
Aditya Toshniwal ad34ee2699 Fixed new line indentation in query editor and add a user preference to disable it. #7295 2024-06-13 18:06:13 +05:30
Aditya Toshniwal e03d65d547 Fixed an issue where query tool shortcuts for find/replace are not working. #7555 2024-06-13 17:26:47 +05:30
Pravesh Sharma b5c8692f34 Fixed an issue where resizable data editors in query tool should not be allowed to resize beyond the app window bounds. #7241 2024-06-13 14:07:44 +05:30
Akshay Joshi f96977733f Downgrade some more packages to ensure compatibility with Debian 10 2024-06-13 12:27:24 +05:30
Akshay Joshi 33bd02d337 Downgrade boto3 to ensure compatibility with Debian 10. 2024-06-13 11:26:15 +05:30
Akshay Joshi ab01dde2ba Fixed RESQL test case. 2024-06-12 18:46:12 +05:30
Akshay Joshi dea5335ce5 Fixed the following SonarQube code smells:
1) Do not use the Array index in keys.
2) Import from the same module should be merged.
3) Mutable variables should not be exported.
4) Variables should not be initialized to undefined.
5) startswith or endswith method should be used.
6) Unwrap this unnecessarily grouped subpattern.

Additionally, addressed many other SonarQube rules.
2024-06-12 18:09:06 +05:30
Rohit Bhati 288fd7ed12 Add support for comments on RLS policy object. #7414 2024-06-12 17:18:55 +05:30
Rohit Bhati c98cea2ea9 Search Objects dialog should focus on search input on open. #7536 2024-06-12 17:17:35 +05:30
Aditya Toshniwal 056aff4742 Revert the changes done for removing support for Python 3.7 2024-06-12 16:23:27 +05:30
Yogesh Mahajan 6357672387 Provide an option to set the theme based on the OS theme. #5932 2024-06-12 16:18:37 +05:30
Yogesh Mahajan bdadc77235 Ensure preferences can be loaded using preferences.json. #7516 2024-06-12 12:07:28 +05:30
dependabot[bot] 0cb75bdcab Python dependency: Bump azure-identity in /web/regression
Bumps [azure-identity](https://github.com/Azure/azure-sdk-for-python) from 1.16.0 to 1.16.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-identity_1.16.0...azure-identity_1.16.1)

---
updated-dependencies:
- dependency-name: azure-identity
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-12 11:44:55 +05:30
dependabot[bot] bc3052ed1b Python dependency: Bump testtools from 2.7.1 to 2.7.2 in /web/regression
Bumps [testtools](https://github.com/testing-cabal/testtools) from 2.7.1 to 2.7.2.
- [Release notes](https://github.com/testing-cabal/testtools/releases)
- [Changelog](https://github.com/testing-cabal/testtools/blob/master/NEWS)
- [Commits](https://github.com/testing-cabal/testtools/compare/2.7.1...2.7.2)

---
updated-dependencies:
- dependency-name: testtools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-12 11:44:31 +05:30
Akshay Joshi df2f3460f0 Fix the following SonarQube code smells:
1) Use the "RegExp.exec()" method instead.
2) Remove parameter form or provide default value.
3) Extract this nested ternary operation into an independent statement.
4) Replace this character class by the character itself.
5) Unnecessary use of conditional expression for default assignment.
6) Prefer using an optional chain expression instead, as it's more concise and easier to read.
2024-06-11 18:07:22 +05:30
Aditya Toshniwal bdf4f39b2b - Update release notes.
- Update more JS packages.
2024-06-11 15:28:21 +05:30
Yogesh Mahajan fff192eb95 Ensure that a user can connect to a server using SSL certificates and identity files from a shared storage. #7306 2024-06-11 14:48:11 +05:30
Akshay Joshi c47390e643 Fixed API test cases for BatchProcess 2024-06-11 12:59:48 +05:30
Ahmad fd944280f1 Fixed an issue where dark theme shows white background when all tabs are closed. #7481 2024-06-11 12:03:43 +05:30
Khushboo Vashi fa71b06874 Set the permission for the installation directory without fakeroot. 2024-06-11 10:41:47 +05:30
Khushboo Vashi 591308fbe8 chmod doesn't work with fakeroot in a single command. 2024-06-10 18:45:44 +05:30
Akshay Joshi a03b513389 Revert changes for yarn.lock 2024-06-10 18:15:05 +05:30
Akshay Joshi 8857f0d179 Fix SonarQube code smells:
1) String literals should not be duplicated.
2) Prefer using an optional chain expression instead, as it's more concise and easier to read.
3) Expected the Promise rejection reason to be an Error.
2024-06-10 18:04:32 +05:30
Khushboo Vashi 2d2aa45ec5 Another attempt to fix Debian installation directory permission. 2024-06-10 16:50:59 +05:30
Khushboo Vashi ba5b66ff4f Fix Debian installation directory permission. 2024-06-10 16:11:09 +05:30
oon arfiandwiandWeblate Admin 285e3afeee Indonesian translation for version 8.9
* Added translation using Weblate (Indonesian)

* Added translation using Weblate (Indonesian)

* Translated using Weblate (Indonesian)

---------

Co-authored-by: Weblate Admin <admin@example.com>
2024-06-10 11:33:03 +05:30
Akshay Joshi b3cf9ce185 Unpin dnspython from 'regression/requirements.txt' as eventlet issue is fixed. 2024-06-07 17:52:46 +05:30
dependabot[bot] 18deb16e36 Python dependency: Bump pbr from 5.11.1 to 6.0.0 in /web/regression
Bumps [pbr](https://docs.openstack.org/pbr/latest/) from 5.11.1 to 6.0.0.

---
updated-dependencies:
- dependency-name: pbr
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:53:22 +05:30
dependabot[bot] 1a1266a5d6 Python dependency: Bump azure-identity from 1.15.0 to 1.16.0
Bumps [azure-identity](https://github.com/Azure/azure-sdk-for-python) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-identity_1.15.0...azure-identity_1.16.0)

---
updated-dependencies:
- dependency-name: azure-identity
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:49:53 +05:30
dependabot[bot] 7cdcaa0533 Python dependency: Bump azure-mgmt-resource in /web/regression
Bumps [azure-mgmt-resource](https://github.com/Azure/azure-sdk-for-python) from 23.0.1 to 23.1.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-mgmt-resource_23.0.1...azure-mgmt-resource_23.1.1)

---
updated-dependencies:
- dependency-name: azure-mgmt-resource
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:49:30 +05:30
dependabot[bot] d5f6802e5f Python dependency: Bump azure-identity in /web/regression
Bumps [azure-identity](https://github.com/Azure/azure-sdk-for-python) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/esrp_release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-identity_1.15.0...azure-identity_1.16.0)

---
updated-dependencies:
- dependency-name: azure-identity
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:49:11 +05:30
dependabot[bot] bc1a2a0b4d Python dependency: Bump selenium in /web/regression
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.19.0 to 4.21.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.19.0...selenium-4.21.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:39:53 +05:30
dependabot[bot] 7cb1d74c05 Python dependency: Update setuptools requirement from ==69.* to ==70.*
Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v69.0.0...v70.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:39:31 +05:30
dependabot[bot] 02dbb20b41 Python dependency: Update setuptools requirement in /web/regression
Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v69.0.0...v70.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:38:56 +05:30
Akshay Joshi 6b9e3f5d1c Update release note. 2024-06-07 15:54:41 +05:30
Aditya Toshniwal 5f4db94179 Update yarn.lock file 2024-06-07 15:21:13 +05:30
Aditya Toshniwal de712b0805 - Update JS packages.
- Remove support for Python 3.7 as Debian 10 is EOL.
2024-06-07 14:17:22 +05:30
dependabot[bot] fdfd6c7792 Python dependency: Update boto3 requirement in /web/regression
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.33.0...1.34.86)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 18:14:14 +05:30
dependabot[bot] c6739ebd6b Python dependency: Bump dnspython from 2.3.0 to 2.6.1 in /web/regression
Bumps [dnspython](https://github.com/rthalley/dnspython) from 2.3.0 to 2.6.1.
- [Release notes](https://github.com/rthalley/dnspython/releases)
- [Changelog](https://github.com/rthalley/dnspython/blob/main/doc/whatsnew.rst)
- [Commits](https://github.com/rthalley/dnspython/compare/v2.3.0...v2.6.1)

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 18:11:47 +05:30
dependabot[bot] f673e68677 Python dependency: Bump eventlet from 0.34.2 to 0.36.1
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.34.2 to 0.36.1.
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.34.2...0.36.1)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 18:09:33 +05:30
Rohit Bhati 85d4473af4 Disable the query tool editor input if any SQL is being loaded to prevent users from typing. #6357 2024-06-06 18:06:49 +05:30
dependabot[bot] 45cafd2cff Python dependency: Update boto3 requirement from ==1.33.* to ==1.34.*
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.33.0...1.34.86)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 18:03:50 +05:30
dependabot[bot] d5ac441ab7 Python dependency: Bump psycopg[c] in /web/regression
Bumps [psycopg[c]](https://github.com/psycopg/psycopg) from 3.1.12 to 3.1.19.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.1.12...3.1.19)

---
updated-dependencies:
- dependency-name: psycopg[c]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 18:01:42 +05:30
dependabot[bot] 8e372f194c Python dependency: Update bcrypt requirement in /web/regression
Updates the requirements on [bcrypt](https://github.com/pyca/bcrypt) to permit the latest version.
- [Changelog](https://github.com/pyca/bcrypt/blob/main/release.py)
- [Commits](https://github.com/pyca/bcrypt/compare/4.0.0...4.1.2)

---
updated-dependencies:
- dependency-name: bcrypt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 17:58:48 +05:30
dependabot[bot] 55ad67ac52 Javascript dependency: Bump eslint from 9.2.0 to 9.4.0
Bumps [eslint](https://github.com/eslint/eslint) from 9.2.0 to 9.4.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.2.0...v9.4.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 17:58:03 +05:30
Yogesh Mahajan cc999ae5a5 Remove the usage of MUI makeStyles as it doesn't support React 18. #7363 2024-06-06 17:13:12 +05:30
Khushboo Vashi f66bd4bcfb Remove the use of is_normalized function for Python 3.7. 2024-06-05 14:11:59 +05:30
Akshay Joshi dfaea944f0 Revert "Detect if running in Flatpak; patch pythonPath and pgadminFile accordingly."
This reverts commit d98ee76b8d.
2024-06-04 20:35:25 +05:30
Akshay Joshi ff287f32c5 Update version for release v8.8 2024-06-04 18:22:35 +05:30
Akshay Joshi a46f99d360 1) Partially fixed the issue with inserting characters at the end of the line by setting 'Underline query at cursor?' to false by default.
2) Update release note.
2024-06-04 18:18:16 +05:30
Kolja d98ee76b8d Detect if running in Flatpak; patch pythonPath and pgadminFile accordingly. 2024-06-04 15:36:08 +05:30
Akshay Joshi 29a526626f Fixed an issue where the size displayed as 'NaN B' for all databases in the statistics tab. #7524 2024-06-03 17:10:11 +05:30
Khushboo Vashi 6509e45b6f Fix the issue where docker with SSL v8.7 fails to start. #7520 2024-05-31 14:29:36 +05:30
Akshay Joshi 2fb5b26adb Update release note. 2024-05-31 11:26:15 +05:30
Khushboo Vashi 24aefd2c7a Fix an issue where user authentication fails with special characters in password. #5785 2024-05-31 11:22:36 +05:30
Pravesh Sharma b5b0538fe3 Fixed an issue where canceling a query without privilege does not display any message on query tool. #7480 2024-05-31 11:19:44 +05:30
453 changed files with 45509 additions and 37562 deletions

No files matched your search

-1
View File
@@ -1,4 +1,3 @@
.git
web/node_modules
web/*.log
web/regression
+6 -1
View File
@@ -18,6 +18,11 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Build the container
run: docker build .
uses: docker/build-push-action@v6
with:
push: false
context: .
+3
View File
@@ -9,6 +9,7 @@
.DS_Store
.idea
.vscode
.sonarlint
.yarn
/*.diff
/*.patch
@@ -38,6 +39,7 @@ runtime/pgAdmin4.app/
runtime/pgAdmin4.pro.user*
runtime/pgAdmin4_resource.rc
runtime/release/
runtime/dev_config.json
runtime/ui_BrowserWindow.h
web/config_local.py
web/pgadmin/misc/themes/pgadmin.themes.json
@@ -48,6 +50,7 @@ node_modules/
web/pgAdmin/static/js/generated
web/pgadmin/static/js/generated
web/yarn-error.log
web/commit_hash
/web/cacert.pem
auditjs.html
auditpy.txt
+6 -4
View File
@@ -31,6 +31,7 @@ RUN apk add --no-cache \
yarn \
zlib-dev
COPY .git .git
# Create the /pgadmin4 directory and copy the source into it. Explicitly
# remove the node_modules directory as we'll recreate a clean version, as well
# as various other files we don't want
@@ -60,7 +61,8 @@ RUN export CPPFLAGS="-DPNG_ARM_NEON_OPT=0" && \
webpack.* \
jest.config.js \
babel.* \
./pgadmin/static/js/generated/.cache
./pgadmin/static/js/generated/.cache \
/pgadmin4/.git
#########################################################################
# Next, create the base environment for Python
@@ -70,7 +72,7 @@ FROM alpine:latest AS env-builder
# Install dependencies
COPY requirements.txt /
RUN apk add --no-cache \
RUN apk add --no-cache \
make \
python3 \
py3-pip && \
@@ -187,7 +189,7 @@ COPY LICENSE /pgadmin4/LICENSE
COPY DEPENDENCIES /pgadmin4/DEPENDENCIES
# Install runtime dependencies and configure everything in one RUN step
RUN apk add \
RUN apk add --no-cache \
python3 \
py3-pip \
postfix \
@@ -199,7 +201,7 @@ RUN apk add \
libedit \
libldap \
libcap && \
/venv/bin/python3 -m pip install --no-cache-dir gunicorn==20.1.0 && \
/venv/bin/python3 -m pip install --no-cache-dir gunicorn==22.0.0 && \
find / -type d -name '__pycache__' -exec rm -rf {} + && \
useradd -r -u 5050 -g root -s /sbin/nologin pgadmin && \
mkdir -p /run/pgadmin /var/lib/pgadmin && \
+39 -33
View File
@@ -217,6 +217,8 @@ REM Main build sequence Ends
ECHO Installing javascript dependencies...
CD "%BUILDROOT%\web"
CALL yarn set version berry || EXIT /B 1
CALL yarn set version 3 || EXIT /B 1
CALL yarn install || EXIT /B 1
CALL npm rebuild || EXIT /B 1
@@ -260,45 +262,51 @@ REM Main build sequence Ends
RD /Q /S "%BUILDROOT%\docs\en_US\html\_sources" 1> nul 2>&1
ECHO Staging runtime components...
XCOPY /S /I /E /H /Y "%WD%\runtime\assets" "%BUILDROOT%\runtime\assets" > nul || EXIT /B 1
XCOPY /S /I /E /H /Y "%WD%\runtime\src" "%BUILDROOT%\runtime\src" > nul || EXIT /B 1
MKDIR "%BUILDROOT%\runtime\resources\app"
XCOPY /S /I /E /H /Y "%WD%\runtime\assets" "%BUILDROOT%\runtime\resources\app\assets" > nul || EXIT /B 1
XCOPY /S /I /E /H /Y "%WD%\runtime\src" "%BUILDROOT%\runtime\resources\app\src" > nul || EXIT /B 1
COPY "%WD%\runtime\package.json" "%BUILDROOT%\runtime\" > nul || EXIT /B 1
CD "%BUILDROOT%\runtime\"
CALL yarn install --production=true || EXIT /B 1
COPY "%WD%\runtime\package.json" "%BUILDROOT%\runtime\resources\app\" > nul || EXIT /B 1
COPY "%WD%\runtime\.yarnrc.yml" "%BUILDROOT%\runtime\resources\app\" > nul || EXIT /B 1
ECHO Downloading NWjs to %TMPDIR%...
REM Get a fresh copy of nwjs.
REM NOTE: The nw download servers seem to be very unreliable, so at the moment we're using wget which retries
CD "%BUILDROOT%\runtime\resources\app\"
REM YARN
REM CALL yarn --cwd "%TMPDIR%" add nw || EXIT /B
REM YARN END
CALL yarn set version berry || EXIT /B 1
CALL yarn set version 3 || EXIT /B 1
CALL yarn plugin import workspace-tools || EXIT /B 1
CALL yarn workspaces focus --production || EXIT /B 1
ECHO Removing yarn cache...
RD /Q /S "%BUILDROOT%\runtime\resources\app\.yarn" 1> nul 2>&1
ECHO Downloading Electron to %TMPDIR%...
REM Get a fresh copy of electron.
REM WGET
REM Comment out the below line as the latest version having some
REM problem https://github.com/nwjs/nw.js/issues/7964, so for the time being
REM hardcoded the version to 0.77.0
REM FOR /f "tokens=2 delims='" %%i IN ('yarn info nw ^| findstr "latest: "') DO SET "NW_VERSION=%%i"
REM :GET_NW
REM wget https://dl.nwjs.io/v%NW_VERSION%/nwjs-v%NW_VERSION%-win-x64.zip -O "%TMPDIR%\nwjs-v%NW_VERSION%-win-x64.zip"
REM IF %ERRORLEVEL% NEQ 0 GOTO GET_NW
FOR /f "tokens=*" %%i IN ('npm info electron version') DO SET "ELECTRON_VERSION=%%i"
:GET_NW
wget https://github.com/electron/electron/releases/download/v%ELECTRON_VERSION%/electron-v%ELECTRON_VERSION%-win32-x64.zip -O "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64.zip"
IF %ERRORLEVEL% NEQ 0 GOTO GET_NW
SET "NW_VERSION=0.77.0"
wget https://dl.nwjs.io/v%NW_VERSION%/nwjs-v%NW_VERSION%-win-x64.zip -O "%TMPDIR%\nwjs-v%NW_VERSION%-win-x64.zip"
tar -C "%TMPDIR%" -xvf "%TMPDIR%\nwjs-v%NW_VERSION%-win-x64.zip" || EXIT /B 1
MKDIR "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64" || EXIT /B 1
tar -C "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64" -xvf "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64.zip" || EXIT /B 1
REM WGET END
REM YARN
REM XCOPY /S /I /E /H /Y "%TMPDIR%\node_modules\nw\nwjs\*" "%BUILDROOT%\runtime" > nul || EXIT /B 1
REM YARN END
REM XCOPY
XCOPY /S /I /E /H /Y "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64\*" "%BUILDROOT%\runtime" > nul || EXIT /B 1
REM XCOPY END
REM WGET
XCOPY /S /I /E /H /Y "%TMPDIR%\nwjs-v%NW_VERSION%-win-x64\*" "%BUILDROOT%\runtime" > nul || EXIT /B 1
REM WGET END
MOVE "%BUILDROOT%\runtime\electron.exe" "%BUILDROOT%\runtime\pgAdmin4.exe"
ECHO Downloading rcedit.exe...
wget https://github.com/electron/rcedit/releases/download/v2.0.0/rcedit-x64.exe -O "%TMPDIR%\rcedit-x64.exe"
ECHO Replacing executable icon, description, version...
%TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-icon "%WD%\pkg\win32\Resources\pgAdmin4.ico"
%TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-version-string "FileDescription" "%APP_NAME%"
%TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-version-string "ProductName" "%APP_NAME%"
%TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-product-version "%APP_VERSION%""
MOVE "%BUILDROOT%\runtime\nw.exe" "%BUILDROOT%\runtime\pgAdmin4.exe"
ECHO Attempting to sign the pgAdmin4.exe...
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /tr http://timestamp.digicert.com "%BUILDROOT%\runtime\pgAdmin4.exe"
IF %ERRORLEVEL% NEQ 0 (
@@ -309,10 +317,6 @@ REM Main build sequence Ends
PAUSE
)
ECHO Replacing executable icon...
CALL yarn --cwd "%TMPDIR%" add winresourcer || EXIT /B
"%TMPDIR%\node_modules\winresourcer\bin\Resourcer.exe" -op:upd -src:"%BUILDROOT%\runtime\pgAdmin4.exe" -type:Icongroup -name:IDR_MAINFRAME -file:"%WD%\pkg\win32\Resources\pgAdmin4.ico"
ECHO Staging PostgreSQL components...
COPY "%PGADMIN_POSTGRES_DIR%\bin\libpq.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
COPY "%PGADMIN_POSTGRES_DIR%\bin\libcrypto-*-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
@@ -366,6 +370,8 @@ REM Main build sequence Ends
ECHO Generating SBOM...
CALL syft "%BUILDROOT%" -o cyclonedx-json > "%BUILDROOT%\sbom.json"
EXIT /B 0
:SIGN_INSTALLER
ECHO Attempting to sign the installer...
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /tr http://timestamp.digicert.com "%DISTROOT%\%INSTALLERNAME%"
+1
View File
@@ -118,6 +118,7 @@ debian:
docker:
echo $(APP_NAME)
git checkout HEAD
docker build --pull -t ${APP_NAME} -t $(APP_NAME):latest -t $(APP_NAME):$(APP_RELEASE) -t $(APP_NAME):$(APP_RELEASE).$(APP_REVISION) .
docs:
+2 -8
View File
@@ -14,7 +14,7 @@ and ReactJS, HTML5 with CSS for the client side processing and UI.
Although developed using web technologies, pgAdmin 4 can be deployed either on
a web server using a browser, or standalone on a workstation. The runtime/
subdirectory contains an NWjs based runtime application intended to allow this,
subdirectory contains an Electron based runtime application intended to allow this,
which will execute the Python server and display the UI.
## Building the Runtime
@@ -35,13 +35,7 @@ paths it would expect to find in the standard package for your platform.
You can then execute the runtime by running something like:
```bash
node_modules/nw/nwjs/nw .
```
or on macOS:
```bash
node_modules/nw/nwjs/nwjs.app/Contents/MacOS/nwjs .
yarn run start
```
# Configuring the Python Environment
+2 -2
View File
@@ -7,12 +7,12 @@
The bulk of pgAdmin is a Python web application written using the Flask framework
on the backend, and HTML5 with CSS3,ReactJS on the front end. A
desktop runtime is also included for users that prefer a desktop application to
a web application, which is written using NWjs (Node Webkit).
a web application, which is written using Electron.
Runtime
*******
The runtime is based on NWjs which integrates a browser and the Python server
The runtime is based on Electron which integrates a browser and the Python server
creating a standalone application. The source code can be found in the
**/runtime** directory in the source tree.
+1 -1
View File
@@ -36,7 +36,7 @@ See :ref:`config_py` for more information on configuration settings.
Desktop Runtime Standalone Application
======================================
The Desktop Runtime is based on `NWjs <https://nwjs.io/>`_ which integrates a
The Desktop Runtime is based on `Electron <https://www.electronjs.org/>`_ which integrates a
browser and the Python server creating a standalone application.
.. image:: images/runtime_standalone.png
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 78 KiB

+2
View File
@@ -48,6 +48,8 @@ When using main browser window, the following keyboard shortcuts are available:
+----------------------------+--------------------+------------------------------------+
| Shift + Alt + ] | Shift + Option + ] | Tabbed panel forward |
+----------------------------+--------------------+------------------------------------+
| Shift + Alt + w | Shift + Ctrl + w | Close tab panel |
+----------------------------+--------------------+------------------------------------+
| Shift + Alt + l | Shift + Option + l | Tools main menu |
+----------------------------+--------------------+------------------------------------+
| Shift + Alt + v | Shift + Option + v | View data |
+5 -1
View File
@@ -282,7 +282,8 @@ Expand the *Miscellaneous* node to specify miscellaneous display preferences.
* Use the *Themes* drop-down listbox to select the theme for pgAdmin. You'll also get a preview just below the
drop down. You can also submit your own themes,
check `here <https://github.com/pgadmin-org/pgadmin4/blob/master/README.md>`_ how.
Currently we support Standard, Dark and High Contrast theme.
Currently we support Standard, Dark and High Contrast and System theme. Selecting System option will follow
your computer's settings.
The Paths Node
**************
@@ -399,6 +400,9 @@ Use the fields on the *Editor* panel to change settings of the query editor.
changed to text/plain. Keyword highlighting and code folding will be disabled.
This will improve editor performance with large files.
* When the *Highlight selection matches?* switch is set to *True*, the editor will
highlight matched selected text.
.. image:: images/preferences_sql_explain.png
:alt: Preferences dialog sqleditor explain options
:align: center
+2
View File
@@ -194,6 +194,8 @@ Data Editing Options
| | | |
| | * Click the *Paste with SERIAL/IDENTITY values?* if you want to paste the copied column values | |
| | in the serial/identity columns. | |
| | | |
| | Note that copied row having *Bytea* datatype cell will be pasted as *Null*. | |
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
| *Delete* | Click the *Delete* icon to mark the selected rows for deletion. These marked rows get deleted | Option/Alt + |
| | | Shift + D |
+4
View File
@@ -12,6 +12,10 @@ notes for it.
:maxdepth: 1
release_notes_8_11
release_notes_8_10
release_notes_8_9
release_notes_8_8
release_notes_8_7
release_notes_8_6
release_notes_8_5
+59
View File
@@ -0,0 +1,59 @@
************
Version 8.10
************
Release date: 2024-07-29
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v8.9.
Supported Database Servers
**************************
**PostgreSQL**: 12, 13, 14, 15, 16 and 17
**EDB Advanced Server**: 12, 13, 14, 15, and 16
Bundled PostgreSQL Utilities
****************************
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.3
New features
************
| `Issue #3981 <https://github.com/pgadmin-org/pgadmin4/issues/3981>`_ - Add support for Postgres Server Logs for Text, CSV and JSON format in plain and tabular formats. Upgrade React to version 18.
| `Issue #6572 <https://github.com/pgadmin-org/pgadmin4/issues/6572>`_ - Add a keyboard shortcut to close active tab panel.
| `Issue #7530 <https://github.com/pgadmin-org/pgadmin4/issues/7530>`_ - Add support for highlighting selection matches in the query editor.
Housekeeping
************
| `Issue #7494 <https://github.com/pgadmin-org/pgadmin4/issues/7494>`_ - Replace pgAdmin NW.js container with Electron container.
| `Issue #7501 <https://github.com/pgadmin-org/pgadmin4/issues/7501>`_ - Updated to the latest version of the Notistack library.
| `Issue #7537 <https://github.com/pgadmin-org/pgadmin4/issues/7537>`_ - Ensure that pgAdmin 4 is compatible with PostgreSQL v17.
| `Issue #7607 <https://github.com/pgadmin-org/pgadmin4/issues/7607>`_ - Automatically apply virtualization in the DataGridView of SchemaView if the schema contains only one collection.
| `Issue #7623 <https://github.com/pgadmin-org/pgadmin4/issues/7623>`_ - Add the git commit hash details to the About dialog.
Bug fixes
*********
| `Issue #3199 <https://github.com/pgadmin-org/pgadmin4/issues/3199>`_ - Fixed an issue where paste operation in query tool data grid should skip bytea columns and put the value as NULL instead.
| `Issue #4165 <https://github.com/pgadmin-org/pgadmin4/issues/4165>`_ - Fixed an issue where the taskbar icon appeared as a red square for the query tool and schema diff when opened in a new window.
| `Issue #5345 <https://github.com/pgadmin-org/pgadmin4/issues/5345>`_ - Fix issue with missing new added records in download file.
| `Issue #5610 <https://github.com/pgadmin-org/pgadmin4/issues/5610>`_ - Fixed an issue where the File Open dialog did not show files without a dot extension.
| `Issue #6548 <https://github.com/pgadmin-org/pgadmin4/issues/6548>`_ - Ensure pgAdmin never makes network requests to Google etc.
| `Issue #6571 <https://github.com/pgadmin-org/pgadmin4/issues/6571>`_ - Fixed an issue where pop-up notifications from Object Explorer wouldn't get dismissed automatically if the Query Tool was opened.
| `Issue #7035 <https://github.com/pgadmin-org/pgadmin4/issues/7035>`_ - Fixed the permission denied issue for functions of the pgstattuple extension when accessing statistics with a non-admin user.
| `Issue #7219 <https://github.com/pgadmin-org/pgadmin4/issues/7219>`_ - Ensure processes related notifiers disappears.
| `Issue #7297 <https://github.com/pgadmin-org/pgadmin4/issues/7297>`_ - Updated entrypoint.sh to utilize the email-validator package for email validation.
| `Issue #7511 <https://github.com/pgadmin-org/pgadmin4/issues/7511>`_ - Fixed an issue where users could not insert characters at the desired location, as it was added to the end of the line.
| `Issue #7554 <https://github.com/pgadmin-org/pgadmin4/issues/7554>`_ - Fixed an issue where sorting the database activity table on the dashboard by any column caused the details to expand in the wrong position.
| `Issue #7618 <https://github.com/pgadmin-org/pgadmin4/issues/7618>`_ - Fix an issue where the preferences JSON file has no effect when an external database is used.
| `Issue #7626 <https://github.com/pgadmin-org/pgadmin4/issues/7626>`_ - Fixed an issue where theme preview under theme options was broken in pgAdmin server mode.
| `Issue #7627 <https://github.com/pgadmin-org/pgadmin4/issues/7627>`_ - Fixed an issue where users could not autofill their saved passwords in the connect server dialog in the browser.
| `Issue #7638 <https://github.com/pgadmin-org/pgadmin4/issues/7638>`_ - Fixed an issue where Generate Script button should be disabled if no objects are selected in the schema diff result.
| `Issue #7639 <https://github.com/pgadmin-org/pgadmin4/issues/7639>`_ - Fixed an issue where ERD Open/Save shorcuts were not working on Windows/Linux.
| `Issue #7660 <https://github.com/pgadmin-org/pgadmin4/issues/7660>`_ - Add a precautionary check for the query tool connection cursor to fix the error 'NoneType' object has no attribute '_query'.
| `Issue #7662 <https://github.com/pgadmin-org/pgadmin4/issues/7662>`_ - Fixed an issue where boolean values in node details of graphical explain plan were not interpreted correctly.
| `Issue #7663 <https://github.com/pgadmin-org/pgadmin4/issues/7663>`_ - Fixed an issue where Reassign/Drop Owned dialog not opening for Role.
| `Issue #7679 <https://github.com/pgadmin-org/pgadmin4/issues/7679>`_ - Ensure pgadmin does not try to connect to the server if saved password is not available.
| `Issue #7681 <https://github.com/pgadmin-org/pgadmin4/issues/7681>`_ - Ensure that pgAdmin works when opened in an iframe.
+45
View File
@@ -0,0 +1,45 @@
************
Version 8.11
************
Release date: 2024-08-25
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v8.10.
Supported Database Servers
**************************
**PostgreSQL**: 12, 13, 14, 15, 16 and 17
**EDB Advanced Server**: 12, 13, 14, 15, and 16
Bundled PostgreSQL Utilities
****************************
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.3
New features
************
| `Issue #2046 <https://github.com/pgadmin-org/pgadmin4/issues/2046>`_ - Add a home button to the geometry viewer to set original zoom level when the viewer was opened.
Housekeeping
************
| `Issue #7705 <https://github.com/pgadmin-org/pgadmin4/issues/7705>`_ - Upgrade react-data-grid fork to latest and change pgAdmin accordingly.
| `Issue #7776 <https://github.com/pgadmin-org/pgadmin4/issues/7776>`_ - Introduce custom React Hook useSchemaState to simplify SchemaView component.
Bug fixes
*********
| `Issue #7499 <https://github.com/pgadmin-org/pgadmin4/issues/7499>`_ - Fixed an issue where refreshing the Schema Diff tool opened in a new tab caused an error.
| `Issue #7540 <https://github.com/pgadmin-org/pgadmin4/issues/7540>`_ - Fix server heartbeat logging error after deleting the server.
| `Issue #7682 <https://github.com/pgadmin-org/pgadmin4/issues/7682>`_ - Fixed an issue where the Generate Script ignored filter conditions when a parent node was selected.
| `Issue #7683 <https://github.com/pgadmin-org/pgadmin4/issues/7683>`_ - Fixed an issue where delete object(shortcut key) affecting both text and Object Explorer items.
| `Issue #7688 <https://github.com/pgadmin-org/pgadmin4/issues/7688>`_ - Fix an issue where ERD tool should to be able to open saved pgerd file when using keyboard shortcuts.
| `Issue #7728 <https://github.com/pgadmin-org/pgadmin4/issues/7728>`_ - Updated the documentation for web server authentication.
| `Issue #7737 <https://github.com/pgadmin-org/pgadmin4/issues/7737>`_ - Fixed an issue where the REVOKE statement in the create script was throwing an error if the role contained special characters.
| `Issue #7748 <https://github.com/pgadmin-org/pgadmin4/issues/7748>`_ - Improve code highlighting in query editor.
| `Issue #7754 <https://github.com/pgadmin-org/pgadmin4/issues/7754>`_ - Fix an issue where the wheel package is not getting installed on the arm64-based macOS version < 14.
| `Issue #7772 <https://github.com/pgadmin-org/pgadmin4/issues/7772>`_ - Fixed an issue where column resizing is not working in search objects dialog.
| `Issue #7775 <https://github.com/pgadmin-org/pgadmin4/issues/7775>`_ - Fixed an issue where the value in the find box is not updating with selected text in editor if find is already open and re-triggered.
| `Issue #7793 <https://github.com/pgadmin-org/pgadmin4/issues/7793>`_ - Fixed paths for Flatpak broken after Electron changes.
+35
View File
@@ -0,0 +1,35 @@
***********
Version 8.8
***********
Release date: 2024-06-06
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v8.7.
Supported Database Servers
**************************
**PostgreSQL**: 12, 13, 14, 15, and 16
**EDB Advanced Server**: 12, 13, 14, 15, and 16
Bundled PostgreSQL Utilities
****************************
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.3
New features
************
Housekeeping
************
Bug fixes
*********
| `Issue #5785 <https://github.com/pgadmin-org/pgadmin4/issues/5785>`_ - Fix an issue where user authentication fails with special characters in password.
| `Issue #7480 <https://github.com/pgadmin-org/pgadmin4/issues/7480>`_ - Fixed an issue where canceling a query without privilege does not display any message on query tool.
| `Issue #7520 <https://github.com/pgadmin-org/pgadmin4/issues/7520>`_ - Fix the issue where docker with SSL v8.7 fails to start.
| `Issue #7524 <https://github.com/pgadmin-org/pgadmin4/issues/7524>`_ - Fixed an issue where the size displayed as 'NaN B' for all databases in the statistics tab.
| `Issue #7526 <https://github.com/pgadmin-org/pgadmin4/issues/7526>`_ - Fixed an issue where backup and restore operations failed with the error 'This build does not support compression with gzip'.
+50
View File
@@ -0,0 +1,50 @@
***********
Version 8.9
***********
Release date: 2024-06-27
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v8.8.
Supported Database Servers
**************************
**PostgreSQL**: 12, 13, 14, 15, and 16
**EDB Advanced Server**: 12, 13, 14, 15, and 16
Bundled PostgreSQL Utilities
****************************
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.3
New features
************
| `Issue #5932 <https://github.com/pgadmin-org/pgadmin4/issues/5932>`_ - Provide option to set theme based on OS theme preference.
Housekeeping
************
| `Issue #7363 <https://github.com/pgadmin-org/pgadmin4/issues/7363>`_ - Remove the usage of MUI makeStyles as it doesn't support React 18.
Bug fixes
*********
| `Issue #6357 <https://github.com/pgadmin-org/pgadmin4/issues/6357>`_ - Disable the query tool editor input if any SQL is being loaded to prevent users from typing.
| `Issue #7241 <https://github.com/pgadmin-org/pgadmin4/issues/7241>`_ - Fixed an issue where resizable data editors in query tool should not be allowed to resize beyond the app window bounds.
| `Issue #7295 <https://github.com/pgadmin-org/pgadmin4/issues/7295>`_ - Fixed new line indentation in query editor and add a user preference to disable it.
| `Issue #7306 <https://github.com/pgadmin-org/pgadmin4/issues/7306>`_ - Ensure that a user can connect to a server using SSL certificates and identity files from a shared storage.
| `Issue #7316 <https://github.com/pgadmin-org/pgadmin4/issues/7316>`_ - Fixed an issue where object explorer toolbar button not showing shortcut in the tooltip.
| `Issue #7414 <https://github.com/pgadmin-org/pgadmin4/issues/7414>`_ - Add support for comments on RLS policy object.
| `Issue #7476 <https://github.com/pgadmin-org/pgadmin4/issues/7476>`_ - Fixed an issue where changing a column name should reflect in all the constraints in table object dialog and ERD table dialog.
| `Issue #7481 <https://github.com/pgadmin-org/pgadmin4/issues/7481>`_ - Fixed an issue where dark theme shows white background when all tabs are closed.
| `Issue #7516 <https://github.com/pgadmin-org/pgadmin4/issues/7516>`_ - Ensure preferences can be loaded using preferences.json.
| `Issue #7523 <https://github.com/pgadmin-org/pgadmin4/issues/7523>`_ - Fixed an issue where the schema diff incorrectly marked tables as different due to schema-qualified trigger functions in the trigger definitions.
| `Issue #7528 <https://github.com/pgadmin-org/pgadmin4/issues/7528>`_ - Fixed an issue where backslash breaks syntax highlighting.
| `Issue #7536 <https://github.com/pgadmin-org/pgadmin4/issues/7536>`_ - Search Objects dialog should focus on search input on open.
| `Issue #7542 <https://github.com/pgadmin-org/pgadmin4/issues/7542>`_ - Fixed incorrect sorting of size in statistics tab.
| `Issue #7555 <https://github.com/pgadmin-org/pgadmin4/issues/7555>`_ - Fixed an issue where query tool shortcuts for find/replace are not working.
| `Issue #7556 <https://github.com/pgadmin-org/pgadmin4/issues/7556>`_ - Fixed migration failure while using external database.
| `Issue #7593 <https://github.com/pgadmin-org/pgadmin4/issues/7593>`_ - Fixed an issue where query tool auto-complete stops working after connection change.
| `Issue #7605 <https://github.com/pgadmin-org/pgadmin4/issues/7605>`_ - Fix the permissions issue in the pgAdmin installation directory on Debian and RHEL-8 platforms (CVE-2024-6238).
| `Issue #7616 <https://github.com/pgadmin-org/pgadmin4/issues/7616>`_ - Fixed an issue where delete button in Users data was enabled for incorrect rows.
+1
View File
@@ -21,6 +21,7 @@ Use the fields in the *General* tab to define the RLS Policy:
* Use the *Name* field to add a descriptive name for the RLS Policy. The name will be displayed in the *pgAdmin* tree control.
* Use the drop-down listbox next to *Role* to select the Role to which the RLS Policy is to be applied.
* Use the drop-down listbox next to *Type* to select the type of the policy.
* Store notes about the policy in the Comment field.
Click the *Commands* tab to continue.
+28 -5
View File
@@ -9,14 +9,14 @@ display information about the object currently selected in the *pgAdmin* tree
control in the left window. Select a tab to access information about the
highlighted object in the tree control.
.. image:: images/main_dashboard_general.png
:alt: Dashboard panel
.. image:: images/dashboard_activity.png
:alt: Dashboard Activity
:align: center
The graphs and tables on the *Dashboard* tab provides an active analysis of system statistics and the usage
statistics for the selected server or database.
Click the *General* tab to get the usage statistics for the selected server or database:
Click the *Activity* tab to get the usage statistics for the selected server or database:
* The *Server sessions* or *Database sessions* graph displays the interactions
with the server or database.
@@ -30,8 +30,14 @@ Click the *General* tab to get the usage statistics for the selected server or d
or fetched from the buffer cache (but not the operating system's file system
cache) for the server or database.
The *Server activity* panel displays information about sessions, locks, prepared
transactions, and server configuration (if applicable). The information is
.. image:: images/dashboard_stat.png
:alt: Dashboard Activity
:align: center
Click the *Stat* tab to get the usage statistics for the selected server or database:
The *Stat* panel displays information about sessions, locks, prepared
transactions. The information is
presented in context-sensitive tables. Use controls located above the table to:
* Click the *Refresh* button to update the information displayed in each table.
@@ -56,6 +62,23 @@ session:
* Use the *Details* icon (located in the third column) to open the *Details*
tab; the tab displays information about the selected session.
.. image:: images/dashboard_config.png
:alt: Dashboard Activity
:align: center
Click the *Configuration* tab to get the server configuration details.
.. image:: images/dashboard_logs.png
:alt: Dashboard Activity
:align: center
Click the *Logs* tab to get the server logs.
* Use the Log Format switch to select the format you want. Text/Plain, JSON and CSV are supported.
The enable/disable state of the log format depends on the Postgresql.conf setting.
* Use the Logs in tabular format? switch if you want to see the logs in a tabular format.
Click the *System Statistics* tab to get the statistics for the system:
.. image:: images/main_dashboard_sys_statistics_summary.png
+3 -3
View File
@@ -14,12 +14,12 @@
{% trans copyright=copyright|e %}<li class="left" style="margin-left: 10px">&#169; Copyright {{ copyright }}.</li>{% endtrans %}
{%- endif %}
{%- endif %}
<li class="right" style="margin-right: 10px"><a href="genindex.html" title="General Index" accesskey="I">index</a></li>
<li class="right" style="margin-right: 10px"><a href="genindex.html" title="General Index">index</a></li>
{%- if next %}
<li class="right" ><a href="{{ next.link|e }}" title="{{ next.title|striptags|e }}" accesskey="N">next</a> |</li>
<li class="right" ><a href="{{ next.link|e }}" title="{{ next.title|striptags|e }}">next</a> |</li>
{%- endif %}
{%- if prev %}
<li class="right" ><a href="{{ prev.link|e }}" title="{{ prev.title|striptags|e }}" accesskey="P">previous</a> |</li>
<li class="right" ><a href="{{ prev.link|e }}" title="{{ prev.title|striptags|e }}">previous</a> |</li>
{%- endif %}
</ul>
</div>
+1
View File
@@ -37,6 +37,7 @@ and modify the values for the following parameters:
The default value is REMOTE_USER and the possible values are REMOTE_USER,
HTTP_X_FORWARDED_USER, X-Forwarded-User."
.. note:: If REMOTE_USER does not work, try replacing it with either REMOTE-USER or Remote-user.
Master Password
===============
+25 -1
View File
@@ -21,7 +21,7 @@ _setup_dirs
_create_python_virtualenv "debian"
_build_runtime
_build_docs "debian"
_copy_code
_copy_code "debian"
_generate_sbom
#
@@ -57,6 +57,7 @@ Description: The core server package for pgAdmin. pgAdmin is the most popular an
EOF
# Build the Debian package for the server
chmod -R u+rwX,go+rX,go-w "${SERVERROOT}"
fakeroot dpkg-deb --build "${SERVERROOT}" "${DISTROOT}/${APP_NAME}-server_${APP_LONG_VERSION}_${OS_ARCH}.deb"
#
@@ -67,6 +68,27 @@ fakeroot dpkg-deb --build "${SERVERROOT}" "${DISTROOT}/${APP_NAME}-server_${APP_
echo "Creating the desktop package..."
mkdir "${DESKTOPROOT}/DEBIAN"
# Ubuntu 24 requires apparmor profile to work.
OS_ID=$(grep "^ID=" /etc/os-release | awk -F "=" '{ print $2 }')
OS_VERSION=$(grep "^VERSION_ID=" /etc/os-release | awk -F "=" '{ print $2 }' | sed 's/"//g' | awk -F "." '{ print $1 }')
if [ "${OS_ID}" == 'ubuntu' ] && [ "${OS_VERSION}" -ge "24" ]; then
cat << EOF > "${DESKTOPROOT}/DEBIAN/conffiles"
/etc/apparmor.d/pgadmin4
EOF
mkdir -p "${DESKTOPROOT}/etc/apparmor.d"
cp "${SOURCEDIR}/pkg/debian/pgadmin4-aa-profile" "${DESKTOPROOT}/etc/apparmor.d/pgadmin4"
cat << EOF > "${DESKTOPROOT}/DEBIAN/postinst"
#!/bin/sh
echo "Load apparmor pgAdmin profile..."
apparmor_parser -r /etc/apparmor.d/pgadmin4
EOF
chmod 755 "${DESKTOPROOT}/DEBIAN/postinst"
fi
cat << EOF > "${DESKTOPROOT}/DEBIAN/control"
Package: ${APP_NAME}-desktop
Version: ${APP_LONG_VERSION}
@@ -79,6 +101,7 @@ Description: The desktop user interface for pgAdmin. pgAdmin is the most popular
EOF
# Build the Debian package for the desktop
chmod -R u+rwX,go+rX,go-w "${DESKTOPROOT}"
fakeroot dpkg-deb --build "${DESKTOPROOT}" "${DISTROOT}/${APP_NAME}-desktop_${APP_LONG_VERSION}_${OS_ARCH}.deb"
#
@@ -108,6 +131,7 @@ mkdir -p "${WEBROOT}/etc/apache2/conf-available"
cp "${SOURCEDIR}/pkg/debian/pgadmin4.conf" "${WEBROOT}/etc/apache2/conf-available"
# Build the Debian package for the web
chmod -R u+rwX,go+rX,go-w "${WEBROOT}"
fakeroot dpkg-deb --build "${WEBROOT}" "${DISTROOT}/${APP_NAME}-web_${APP_LONG_VERSION}_all.deb"
#
+12
View File
@@ -0,0 +1,12 @@
# This profile allows everything and only exists to give the
# application a name instead of having the label "unconfined"
abi <abi/4.0>,
include <tunables/global>
profile pgadmin4 /usr/pgadmin4/bin/pgadmin4 flags=(unconfined) {
userns,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/pgadmin4>
}
+10 -1
View File
@@ -43,10 +43,19 @@ if [ ! -f /var/lib/pgadmin/pgadmin4.db ]; then
exit 1
fi
if ! echo "${PGADMIN_DEFAULT_EMAIL}" | grep -E "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$" > /dev/null; then
# Validate PGADMIN_DEFAULT_EMAIL
CHECK_EMAIL_DELIVERABILITY="False"
if [ -n "${PGADMIN_CONFIG_CHECK_EMAIL_DELIVERABILITY}" ]; then
CHECK_EMAIL_DELIVERABILITY=${PGADMIN_CONFIG_CHECK_EMAIL_DELIVERABILITY}
fi
is_valid_email=$(cd /pgadmin4/pgadmin/utils && /venv/bin/python3 -c "from validation_utils import validate_email; val = validate_email('${PGADMIN_DEFAULT_EMAIL}', ${CHECK_EMAIL_DELIVERABILITY}); print(val)")
if echo "${is_valid_email}" | grep "False" > /dev/null; then
echo "'${PGADMIN_DEFAULT_EMAIL}' does not appear to be a valid email address. Please reset the PGADMIN_DEFAULT_EMAIL environment variable and try again."
exit 1
fi
# Switch back to root directory for further process
cd /pgadmin4
# Read secret contents
if [ -n "${PGADMIN_DEFAULT_PASSWORD_FILE}" ]; then
+37 -30
View File
@@ -133,55 +133,54 @@ _create_python_virtualenv() {
_build_runtime() {
echo "Assembling the desktop runtime..."
# Get a fresh copy of nwjs.
# NOTE: The nw download servers seem to be very unreliable, so at the moment we're using wget
# in a retry loop as Yarn/Npm don't seem to like that.
# Get a fresh copy of electron.
# YARN:
# yarn add --cwd "${BUILDROOT}" nw
# YARN END
ELECTRON_ARCH="x64"
if [ "$(uname -m)" == "arm64" ]; then
ELECTRON_ARCH="arm64"
fi
# WGET:
# Comment out the below line as the latest version having some
# problem https://github.com/nwjs/nw.js/issues/7964, so for the time being
# hardcoded the version to 0.77.0
# NW_VERSION=$(yarn info nw | grep latest | awk -F "'" '{ print $2}')
NW_VERSION="0.77.0"
ELECTRON_VERSION="$(npm info electron version)"
pushd "${BUILDROOT}" > /dev/null || exit
while true;do
wget "https://dl.nwjs.io/v${NW_VERSION}/nwjs-v${NW_VERSION}-linux-x64.tar.gz" && break
rm "nwjs-v${NW_VERSION}-linux-x64.tar.gz"
wget "https://github.com/electron/electron/releases/download/v${ELECTRON_VERSION}/electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}.zip" && break
rm "electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}.zip"
done
tar -zxvf "nwjs-v${NW_VERSION}-linux-x64.tar.gz"
unzip "electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}.zip" -d "electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}"
popd > /dev/null || exit
# WGET END
# Copy nwjs into the staging directory
# Copy electron into the staging directory
mkdir -p "${DESKTOPROOT}/usr/${APP_NAME}/bin"
# The chmod command below is needed to fix the permission issue of
# the NWjs binaries and files.
# Change the permission for others and group the same as the owner
chmod -R og=u "${BUILDROOT}/nwjs-v${NW_VERSION}-linux-x64"/*
chmod -R og=u "${BUILDROOT}/electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}"/*
# Explicitly remove write permissions for others and group
chmod -R og-w "${BUILDROOT}/nwjs-v${NW_VERSION}-linux-x64"/*
chmod -R og-w "${BUILDROOT}/electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}"/*
# YARN:
# cp -r "${BUILDROOT}/node_modules/nw/nwjs"/* "${DESKTOPROOT}/usr/${APP_NAME}/bin"
# YARN END
BUNDLEDIR="${DESKTOPROOT}/usr/${APP_NAME}/bin"
# WGET:
cp -r "${BUILDROOT}/nwjs-v${NW_VERSION}-linux-x64"/* "${DESKTOPROOT}/usr/${APP_NAME}/bin"
cp -r "${BUILDROOT}/electron-v${ELECTRON_VERSION}-linux-${ELECTRON_ARCH}"/* "${BUNDLEDIR}"
# WGET END
mv "${DESKTOPROOT}/usr/${APP_NAME}/bin/nw" "${DESKTOPROOT}/usr/${APP_NAME}/bin/${APP_NAME}"
mv "${BUNDLEDIR}/electron" "${BUNDLEDIR}/${APP_NAME}"
cp -r "${SOURCEDIR}/runtime/assets" "${DESKTOPROOT}/usr/${APP_NAME}/bin/assets"
cp -r "${SOURCEDIR}/runtime/src" "${DESKTOPROOT}/usr/${APP_NAME}/bin/src"
mkdir -p "${BUNDLEDIR}/resources/app"
cp -r "${SOURCEDIR}/runtime/assets" "${BUNDLEDIR}/resources/app/assets"
cp -r "${SOURCEDIR}/runtime/src" "${BUNDLEDIR}/resources/app/src"
cp "${SOURCEDIR}/runtime/package.json" "${DESKTOPROOT}/usr/${APP_NAME}/bin/"
yarn --cwd "${DESKTOPROOT}/usr/${APP_NAME}/bin" install --production=true
cp "${SOURCEDIR}/runtime/package.json" "${BUNDLEDIR}/resources/app"
cp "${SOURCEDIR}/runtime/.yarnrc.yml" "${BUNDLEDIR}/resources/app"
# Install the runtime node_modules
pushd "${BUNDLEDIR}/resources/app" > /dev/null || exit
yarn set version berry
yarn set version 3
yarn plugin import workspace-tools
yarn workspaces focus --production
popd > /dev/null || exit
# Create the icon
mkdir -p "${DESKTOPROOT}/usr/share/icons/hicolor/128x128/apps/"
@@ -212,10 +211,18 @@ _build_docs() {
_copy_code() {
echo "Copying the server code..."
OS_VERSION=$(grep "^VERSION_ID=" /etc/os-release | awk -F "=" '{ print $2 }' | sed 's/"//g' | awk -F "." '{ print $1 }')
if [ "$1" == 'redhat' ] && [ "${OS_VERSION}" == "8" ]; then
echo "Setting file permission through umask..."
umask u+rwx,go+rx,go-w
fi
# Remove any TCL-related files that may cause us problems
find "${SERVERROOT}/usr/${APP_NAME}/venv/" -name "_tkinter*" -print0 | xargs -0 rm -rf
pushd "${SOURCEDIR}/web" > /dev/null || exit
yarn set version berry
yarn set version 3
yarn install
yarn run bundle
popd > /dev/null || exit
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>%APPID%</string>
<key>CFBundleName</key>
<string>%APPNAME%</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTSDKBuild</key>
<string>23A334</string>
<key>DTSDKName</key>
<string>macosx14.0</string>
<key>DTXcode</key>
<string>1501</string>
<key>DTXcodeBuild</key>
<string>15A507</string>
<key>LSEnvironment</key>
<dict>
<key>MallocNanoZone</key>
<string>0</string>
</dict>
<key>LSUIElement</key>
<true/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>CFBundleDisplayName</key>
<string>%APPNAME%</string>
<key>CFBundleExecutable</key>
<string>%APPNAME%</string>
<key>CFBundleShortVersionString</key>
<string>%APPVER%</string>
</dict>
</plist>
+31 -41
View File
@@ -26,56 +26,37 @@ _build_runtime() {
echo "Assembling the runtime environment..."
test -d "${BUILD_ROOT}" || mkdir "${BUILD_ROOT}"
# Get a fresh copy of nwjs.
# NOTE: The nw download servers seem to be very unreliable, so at the moment we're using wget
# in a retry loop as Yarn/Npm don't seem to like that.
# Get a fresh copy of electron
# uname -m returns "x86_64" on Intel, but we need "x64"
NW_ARCH="x64"
ELECTRON_ARCH="x64"
if [ "$(uname -m)" == "arm64" ]; then
NW_ARCH="arm64"
ELECTRON_ARCH="arm64"
fi
# YARN:
# yarn add --cwd "${BUILDROOT}" nw
# YARN END
# WGET:
# Comment out the below line as the latest version having some
# problem https://github.com/nwjs/nw.js/issues/7964, so for the time being
# hardcoded the version to 0.77.0
# NW_VERSION=$(yarn info nw | grep latest | awk -F "'" '{ print $2}')
NW_VERSION="0.77.0"
ELECTRON_VERSION="$(npm info electron version)"
pushd "${BUILD_ROOT}" > /dev/null || exit
while true;do
wget "https://dl.nwjs.io/v${NW_VERSION}/nwjs-v${NW_VERSION}-osx-${NW_ARCH}.zip" && break
rm "nwjs-v${NW_VERSION}-osx-${NW_ARCH}.zip"
wget "https://github.com/electron/electron/releases/download/v${ELECTRON_VERSION}/electron-v${ELECTRON_VERSION}-darwin-${ELECTRON_ARCH}.zip" && break
rm "electron-v${ELECTRON_VERSION}-darwin-${ELECTRON_ARCH}.zip"
done
unzip "nwjs-v${NW_VERSION}-osx-${NW_ARCH}.zip"
unzip "electron-v${ELECTRON_VERSION}-darwin-${ELECTRON_ARCH}.zip"
popd > /dev/null || exit
# WGET END
# YARN:
# cp -R "${BUILD_ROOT}/node_modules/nw/nwjs/nwjs.app" "${BUILD_ROOT}/"
# YARN END
# WGET:
cp -R "${BUILD_ROOT}/nwjs-v${NW_VERSION}-osx-${NW_ARCH}"/nwjs.app "${BUILD_ROOT}/"
# WGET END
mv "${BUILD_ROOT}/nwjs.app" "${BUNDLE_DIR}"
mv "${BUILD_ROOT}/Electron.app" "${BUNDLE_DIR}"
find "${BUNDLE_DIR}" -exec touch {} \;
# Copy in the runtime code
mkdir "${BUNDLE_DIR}/Contents/Resources/app.nw/"
cp -R "${SOURCE_DIR}/runtime/assets" "${BUNDLE_DIR}/Contents/Resources/app.nw/"
cp -R "${SOURCE_DIR}/runtime/src" "${BUNDLE_DIR}/Contents/Resources/app.nw/"
cp "${SOURCE_DIR}/runtime/package.json" "${BUNDLE_DIR}/Contents/Resources/app.nw/"
cp "${SOURCE_DIR}/runtime/.yarnrc.yml" "${BUNDLE_DIR}/Contents/Resources/app.nw/"
mkdir "${BUNDLE_DIR}/Contents/Resources/app/"
cp -R "${SOURCE_DIR}/runtime/assets" "${BUNDLE_DIR}/Contents/Resources/app/"
cp -R "${SOURCE_DIR}/runtime/src" "${BUNDLE_DIR}/Contents/Resources/app/"
cp "${SOURCE_DIR}/runtime/package.json" "${BUNDLE_DIR}/Contents/Resources/app/"
cp "${SOURCE_DIR}/runtime/.yarnrc.yml" "${BUNDLE_DIR}/Contents/Resources/app/"
# Install the runtime node_modules, then replace the package.json
pushd "${BUNDLE_DIR}/Contents/Resources/app.nw/" > /dev/null || exit
pushd "${BUNDLE_DIR}/Contents/Resources/app/" > /dev/null || exit
yarn set version berry
yarn set version 3
yarn plugin import workspace-tools
@@ -154,6 +135,7 @@ _build_docs() {
source "${BUILD_ROOT}/venv/bin/activate"
pip3 install --upgrade pip
pip3 install -r "${SOURCE_DIR}/requirements.txt"
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
pip3 install sphinx==6.1.3
pip3 install sphinxcontrib-youtube
@@ -178,7 +160,6 @@ _fixup_imports() {
# Find all the files that may need tweaks
TODO=$(find . -perm +0111 -type f -exec file "{}" \; | \
grep -v "Frameworks/Python.framework" | \
grep -v "Frameworks/nwjs" | \
grep -E "Mach-O 64-bit" | \
awk -F ':| ' '{ORS=" "; print $1}' | \
uniq)
@@ -273,10 +254,19 @@ _complete_bundle() {
sed -i '' "s/%APPNAME%/${APP_NAME}/g" "${BUNDLE_DIR}/Contents/Info.plist"
sed -i '' "s/%APPVER%/${APP_LONG_VERSION}/g" "${BUNDLE_DIR}/Contents/Info.plist"
sed -i '' "s/%APPID%/org.pgadmin.pgadmin4/g" "${BUNDLE_DIR}/Contents/Info.plist"
for FILE in "${BUNDLE_DIR}"/Contents/Resources/*.lproj/InfoPlist.strings; do
sed -i '' 's/CFBundleGetInfoString =.*/CFBundleGetInfoString = "Copyright (C) 2013 - 2024, The pgAdmin Development Team";/g' "${FILE}"
sed -i '' 's/NSHumanReadableCopyright =.*/NSHumanReadableCopyright = "Copyright (C) 2013 - 2024, The pgAdmin Development Team";/g' "${FILE}"
echo CFBundleDisplayName = \""${APP_NAME}"\"\; >> "${FILE}"
# Rename helper execs and Update the plist
for helper_exec in "Electron Helper" "Electron Helper (Renderer)" "Electron Helper (Plugin)" "Electron Helper (GPU)"
do
pgadmin_exec=${helper_exec//Electron/pgAdmin 4}
mv "${BUNDLE_DIR}/Contents/Frameworks/${helper_exec}.app/Contents/MacOS/${helper_exec}" "${BUNDLE_DIR}/Contents/Frameworks/${helper_exec}.app/Contents/MacOS/${pgadmin_exec}"
mv "${BUNDLE_DIR}/Contents/Frameworks/${helper_exec}.app" "${BUNDLE_DIR}/Contents/Frameworks/${pgadmin_exec}.app"
info_plist="${BUNDLE_DIR}/Contents/Frameworks/${pgadmin_exec}.app/Contents/Info.plist"
cp Info.plist-helper.in "${info_plist}"
sed -i '' "s/%APPNAME%/${pgadmin_exec}/g" "${info_plist}"
sed -i '' "s/%APPVER%/${APP_LONG_VERSION}/g" "${info_plist}"
sed -i '' "s/%APPID%/org.pgadmin.pgadmin4.helper/g" "${info_plist}"
done
# PkgInfo
@@ -286,10 +276,10 @@ _complete_bundle() {
cp pgAdmin4.icns "${BUNDLE_DIR}/Contents/Resources/app.icns"
# Rename the executable
mv "${BUNDLE_DIR}/Contents/MacOS/nwjs" "${BUNDLE_DIR}/Contents/MacOS/${APP_NAME}"
mv "${BUNDLE_DIR}/Contents/MacOS/Electron" "${BUNDLE_DIR}/Contents/MacOS/${APP_NAME}"
# Rename the app in package.json so the menu looks as it should
sed -i '' "s/\"name\": \"pgadmin4\"/\"name\": \"${APP_NAME}\"/g" "${BUNDLE_DIR}/Contents/Resources/app.nw/package.json"
sed -i '' "s/\"name\": \"pgadmin4\"/\"name\": \"${APP_NAME}\"/g" "${BUNDLE_DIR}/Contents/Resources/app/package.json"
# Import the dependencies, and rewrite any library references
_fixup_imports "${BUNDLE_DIR}"
+3 -3
View File
@@ -4,7 +4,7 @@
<dict>
<!--
Disable Sandboxing. This must be enabled for the app store, but it will
cause NWjs to fail to start with an error like:
cause Electron to fail to start with an error like:
[1004/170922.238911:ERROR:directory_reader_posix.cc(42)] opendir /dev/fd: Operation not permitted (1)
@@ -22,7 +22,7 @@
<string>%TEAMID%.org.pgadmin.pgadmin4</string>
<!--
We have no need for JIT on x86_64, but NWJS won't start without it
We have no need for JIT on x86_64, but Electron won't start without it
on Apple Silicon.
-->
<key>com.apple.security.cs.allow-jit</key>
@@ -50,7 +50,7 @@
<!--
We need to enable this, even though we don't modify our own executables.
Otherwise, NWjs just bombs out.
Otherwise, Electron just bombs out.
-->
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
+7 -1
View File
@@ -48,7 +48,7 @@ mkdir pip-build/pgadmin4/docs
# Build the clean tree
cd web || exit
for FILE in $(git ls-files)
for FILE in $(git ls-files|grep -v regression)
do
echo Adding "${FILE}"
# We use tar here to preserve the path, as Mac (for example) doesn't support cp --parents
@@ -56,9 +56,15 @@ do
tar cf - "${FILE}" | (cd ../pip-build/pgadmin4; tar xf -)
done
yarn set version berry
yarn set version 3
yarn install
yarn run bundle
# Copy the commit_hash file, it doesn't show up in git ls-files
echo Adding "commit_hash"
tar cf - "commit_hash" | (cd ../pip-build/pgadmin4; tar xf -)
for FILE in pgadmin/static/js/generated/*
do
echo Adding "${FILE}"
+12 -1
View File
@@ -10,6 +10,7 @@
import builtins
import os
import sys
import platform
from codecs import open
from importlib.machinery import SourceFileLoader
@@ -40,7 +41,17 @@ kerberos_extras = []
# gssapi in it's own list
for index, req in enumerate(all_requires):
if 'psycopg[c]' in req:
req = req.replace('psycopg[c]', 'psycopg[binary]')
# Starting from Psycopg 3.1.20, ARM64 macOS binary packages are no
# longer available for macOS versions before 14.0.
_req = req.replace('psycopg[c]', 'psycopg[binary]')
req = "psycopg[binary] == 3.1.19; sys_platform == 'darwin' and" \
" platform_machine == 'arm64' and platform_release < '23.0' \n"\
+ _req + "; (sys_platform == 'darwin' and" \
" platform_machine == 'arm64' and" \
" platform_release >= '23.0') or" \
" (sys_platform == 'darwin' and" \
" platform_machine != 'arm64'" \
") or sys_platform != 'darwin'"
if 'gssapi' in req:
kerberos_extras.append(req)
+9 -2
View File
@@ -25,7 +25,7 @@ _setup_dirs
_create_python_virtualenv "redhat"
_build_runtime
_build_docs "redhat"
_copy_code
_copy_code "redhat"
_generate_sbom
# Get an RPM-compatible version number
@@ -80,6 +80,8 @@ fi
cp -rfa %{pga_build_root}/server/* \${RPM_BUILD_ROOT}
%files
%defattr(-,root,root,755)
%dir /usr/pgadmin4
/usr/pgadmin4/*
EOF
@@ -121,6 +123,8 @@ cp -rfa %{pga_build_root}/desktop/* \${RPM_BUILD_ROOT}
/bin/xdg-icon-resource forceupdate
%files
%defattr(-,root,root,755)
%attr(755,root,root) /usr/pgadmin4/bin/pgadmin4
/usr/pgadmin4/bin/*
/usr/share/icons/hicolor/128x128/apps/*
/usr/share/icons/hicolor/64x64/apps/*
@@ -131,7 +135,9 @@ cp -rfa %{pga_build_root}/desktop/* \${RPM_BUILD_ROOT}
/usr/pgadmin4/sbom-desktop.json
EOF
# Build the Redhat package for the server
# Build the Redhat package for the desktop
rpmbuild --define "pga_build_root ${BUILDROOT}" -bb "${BUILDROOT}/desktop.spec"
@@ -168,6 +174,7 @@ The web interface for pgAdmin, hosted under Apache HTTPD. pgAdmin is the most po
cp -rfa %{pga_build_root}/web/* \${RPM_BUILD_ROOT}
%files
%defattr(-,root,root,755)
/usr/pgadmin4/bin/*
%config(noreplace) /etc/httpd/conf.d/*
/usr/pgadmin4/sbom-web.json
+3
View File
@@ -39,14 +39,17 @@ yum groupinstall -y "Development Tools"
if [ "${OS_VERSION}" == "8" ]; then
yum install -y expect fakeroot postgresql15-devel python3.9-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
pip3.9 install sphinx==6.1.3
pip3.9 install sphinxcontrib-youtube
elif [ "${OS_VERSION}" == "9" ]; then
yum install -y expect libpq5-devel postgresql15-devel python3-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
pip3 install sphinx==6.1.3
pip3 install sphinxcontrib-youtube
else
yum install -y expect fakeroot postgresql15-devel python3-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
pip3 install sphinx==6.1.3
pip3 install sphinxcontrib-youtube
fi
+7
View File
@@ -32,6 +32,9 @@ fi
TARBALL_NAME=$(echo "${APP_NAME}-${APP_LONG_VERSION}" | sed 's/ //g' | awk '{print tolower($0)}')
DOC_TARBALL_NAME=$(echo "${APP_NAME}-${APP_LONG_VERSION}-docs" | sed 's/ //g' | awk '{print tolower($0)}')
# Get the github timestamp
git log -1 --format='%H %as' > web/commit_hash
# Output basic details to show we're working
echo "Building tarballs for ${APP_NAME} version ${APP_LONG_VERSION}..."
@@ -69,6 +72,10 @@ do
tar cf - "${FILE}" | (cd "src-build/${TARBALL_NAME}"; tar xf -)
done
# Copy the commit_hash file, it doesn't show up in git ls-files
echo Adding "web/commit_hash"
tar cf - "web/commit_hash" | (cd "src-build/${TARBALL_NAME}"; tar xf -)
# Create the tarball
echo Creating tarball...
cd src-build || exit
+20 -29
View File
@@ -8,59 +8,50 @@
#
###############################################################################
Flask==3.0.*; python_version > '3.7'
Flask==2.2.*; python_version <= '3.7'
Flask==3.0.*
Flask-Login==0.*
Flask-Mail==0.*
Flask-Migrate==4.*
greenlet==1.1.2; python_version <= '3.10'
Flask-SQLAlchemy==3.1.*; python_version > '3.7'
Flask-SQLAlchemy==3.0.*; python_version <= '3.7'
Flask-WTF==1.2.*; python_version > '3.7'
Flask-WTF==1.1.1; python_version <= '3.7'
Flask-SQLAlchemy==3.1.*
Flask-WTF==1.2.*
Flask-Compress==1.*
Flask-Paranoid==0.*
Flask-Babel==4.0.*; python_version > '3.7'
Flask-Babel==3.1.*; python_version <= '3.7'
Flask-Security-Too==5.4.*; python_version > '3.7'
Flask-Security-Too==5.1.*; python_version <= '3.7'
Flask-Babel==4.0.*
Flask-Security-Too==5.5.*; python_version >= '3.10'
Flask-Security-Too==5.4.*; python_version <= '3.9'
Flask-SocketIO==5.3.*
WTForms==3.1.*; python_version > '3.7'
WTForms==3.0.*; python_version <= '3.7'
WTForms==3.1.*
passlib==1.*
pytz==2024.*
speaklater3==1.*
sqlparse==0.*
psutil==5.9.*
psycopg[c]==3.1.12
psutil==6.0.*
psycopg[c]==3.2.1
python-dateutil==2.*
SQLAlchemy==2.*
bcrypt==4.0.*
cryptography==42.0.*
bcrypt==4.2.*
cryptography==43.0.*
sshtunnel==0.*
ldap3==2.*
gssapi==1.8.*
eventlet==0.34.2
httpagentparser==1.9.*
eventlet==0.36.1
user-agents==2.2.0
pywinpty==2.0.*; sys_platform=="win32"
Authlib==1.3.*; python_version > '3.7'
Authlib==1.2.*; python_version <= '3.7'
Authlib==1.3.*
pyotp==2.*
qrcode==7.*
boto3==1.33.*
boto3==1.34.*
urllib3==1.26.*
azure-mgmt-rdbms==10.1.0
azure-mgmt-resource==23.0.1
azure-mgmt-resource==23.1.1
azure-mgmt-subscription==3.1.1
azure-identity==1.15.0
azure-identity==1.17.1
google-api-python-client==2.*
google-auth-oauthlib==1.2.0
keyring==24.*; python_version > '3.7'
keyring==23.*; python_version <= '3.7'
Werkzeug==3.0.*; python_version > '3.7'
Werkzeug==2.2.3; python_version <= '3.7'
google-auth-oauthlib==1.2.1
keyring==25.*
Werkzeug==3.0.*
typer[all]==0.12.*
setuptools==69.*; python_version >= '3.12'
setuptools==72.*; python_version >= '3.12'
jsonformatter~=0.3.2
libgravatar==1.0.*
-6
View File
@@ -1,6 +0,0 @@
generated
node_modules
vendor
templates/
templates\
ycache
+49 -41
View File
@@ -6,47 +6,55 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import globals from 'globals';
import js from '@eslint/js';
module.exports = {
'env': {
'browser': true,
'es6': true,
'amd': true,
},
'extends': [
'eslint:recommended',
],
'parserOptions': {
'ecmaVersion': 2018,
"sourceType": "module",
},
'globals': {
'_': true,
'module': true,
'process': true,
'nw': true,
'platform': true
},
'rules': {
'indent': [
'error',
2
export default [
js.configs.recommended,
{
files: ['**/*.js'],
ignores: [
'generated',
'node_modules',
'vendor',
'templates/',
'templates\\',
'ycache',
],
'linebreak-style': 0,
'quotes': [
'error',
'single'
],
'semi': [
'error',
'always'
],
'comma-dangle': [
'error',
'always-multiline'
],
'no-console': ["error", { allow: ["warn", "error"] }],
// We need to exclude below for RegEx case
"no-useless-escape": 0,
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
globals: {
...globals.browser,
...globals.es2017,
...globals.amd,
'_': 'readonly',
'module': 'readonly',
'process': 'readonly',
'platform': 'readonly',
},
},
'rules': {
'indent': [
'error',
2,
],
'linebreak-style': 0,
'quotes': [
'error',
'single',
],
'semi': [
'error',
'always',
],
'comma-dangle': [
'error',
'always-multiline',
],
'no-console': ['error', { allow: ['warn', 'error'] }],
// We need to exclude below for RegEx case
'no-useless-escape': 0,
},
},
};
];
+15 -27
View File
@@ -1,37 +1,25 @@
{
"name": "pgadmin4",
"description": "pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.",
"main": "src/html/pgadmin.html",
"repository": "https://github.com/postgres/pgadmin4.git",
"author": "pgAdmin Development Team (https://www.pgadmin.org/)",
"license": "PostgreSQL",
"chromium-args": "--disable-popup-blocking --disable-gpu --disable-devtools",
"user-agent": "Nwjs:%nwver-%osinfo-%chromium_ver",
"nodejs": true,
"window": {
"width": 750,
"height": 600,
"toolbar": false,
"fullscreen": false,
"frame": false,
"show": true,
"position": "center",
"always-on-top": true,
"icon": "assets/pgAdmin4.png"
"type": "module",
"main": "src/js/pgadmin.js",
"scripts": {
"start": "electron .",
"linter": "yarn run eslint -c .eslintrc.js ."
},
"icons": {
"256": "assets/pgAdmin4.png"
"packageManager": "yarn@3.8.2",
"devDependencies": {
"@eslint/js": "^9.8.0",
"electron": "latest",
"eslint": "^9.8.0"
},
"dependencies": {
"axios": "^1.6.8",
"bootstrap": "^4.5.3"
},
"devDependencies": {
"eslint": "^9.2.0",
"nw": "0.77.0"
},
"scripts": {
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js ."
},
"packageManager": "yarn@3.6.4"
"axios": "^1.7.4",
"bootstrap": "^4.5.3",
"electron-context-menu": "^4.0.1",
"electron-store": "^10.0.0"
}
}
+95 -2
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>pgAdmin 4 Configuration</title>
<title>pgAdmin 4 Runtime Configuration</title>
<link rel="stylesheet" href="../css/pgadmin-desktop.css"/>
<style>
body, html {
@@ -76,6 +76,99 @@
<button id="btnSave" type="submit" class="btn btn-primary" disabled>Save</button>
</div>
</div>
<script type="text/javascript" src="../js/configure.js"></script>
<script type="text/javascript" >
let configData;
async function checkConfiguration() {
const portNo = configData.portNo;
if (document.getElementById('fixedPortCheck').checked && portNo !== document.getElementById('portNo').value) {
let fixedPort = parseInt(document.getElementById('portNo').value);
// get the available TCP port
if(await window.electronUI.checkPortAvailable(fixedPort)) {
saveConfiguration();
} else {
alert('The port specified is already in use. Please enter a free port number.');
}
} else {
saveConfiguration();
}
}
async function saveConfiguration() {
await window.electronUI.setConfigData({
'fixedPort': document.getElementById('fixedPortCheck').checked,
'portNo': parseInt(document.getElementById('portNo').value),
'connectionTimeout': parseInt(document.getElementById('timeOut').value),
'openDocsInBrowser': document.getElementById('openDocsInBrowser').checked
});
document.getElementById('status-text').innerHTML = 'Configuration Saved';
const result = await window.electronUI.showMessageBox({
'type': 'question',
'title': 'Confirmation',
'message': "pgAdmin 4 must be restarted for changes to take effect.\n\n Do you want to quit the application?",
'buttons': [
'Yes',
'No'
]
});
if(result.response === 0) {
window.electronUI.restartApp();
}
window.close();
}
function onCheckChange() {
if (this.checked) {
document.getElementById('portNo').removeAttribute('disabled');
} else {
document.getElementById('portNo').setAttribute('disabled', 'disabled');
}
// Enable/Disable Save button
enableDisableSaveButton();
}
function enableDisableSaveButton() {
if (configData['fixedPort'] !== document.getElementById('fixedPortCheck').checked ||
configData['portNo'] != document.getElementById('portNo').value ||
configData['connectionTimeout'] != document.getElementById('timeOut').value ||
configData['openDocsInBrowser'] !== document.getElementById('openDocsInBrowser').checked) {
document.getElementById('btnSave').removeAttribute('disabled');
} else {
document.getElementById('btnSave').setAttribute('disabled', 'disabled');
}
}
window.onload = async function() {
configData = await window.electronUI.getConfigData();
document.getElementById('status-text').innerHTML = '';
// Set the GUI value as per configuration.
if (configData['fixedPort']) {
document.getElementById('fixedPortCheck').checked = true;
document.getElementById('portNo').disabled = false;
} else {
document.getElementById('fixedPortCheck').checked = false;
document.getElementById('portNo').disabled = true;
}
document.getElementById('portNo').value = configData['portNo'];
document.getElementById('timeOut').value = configData['connectionTimeout'];
if (configData['openDocsInBrowser']) {
document.getElementById('openDocsInBrowser').checked = true;
} else {
document.getElementById('openDocsInBrowser').checked = false;
}
// Add event listeners
document.getElementById('btnSave').addEventListener('click', checkConfiguration);
document.getElementById('fixedPortCheck').addEventListener('change', onCheckChange);
document.getElementById('portNo').addEventListener('change', enableDisableSaveButton);
document.getElementById('timeOut').addEventListener('change', enableDisableSaveButton);
document.getElementById('openDocsInBrowser').addEventListener('change', enableDisableSaveButton);
};
</script>
</body>
</html>
+9 -1
View File
@@ -31,6 +31,14 @@
</div>
</div>
</div>
<script type="text/javascript" src="../js/server_error.js"></script>
<script>
window.onload = async function() {
document.getElementById('server_error_label').innerHTML = 'The pgAdmin 4 server could not be contacted:';
document.getElementById('server_error_log').innerHTML = await window.electronUI.readServerLog();
document.getElementById('btnConfigure').addEventListener('click', function() {
window.electronUI.openConfigure();
});
}
</script>
</body>
</html>
@@ -19,6 +19,7 @@
background-size: contain;
overflow: hidden;
display: flex;
-webkit-app-region: drag;
}
.loader-text {
@@ -50,9 +51,7 @@
</head>
<body>
<div class="bg">
<span id="loader-text-status" class="loader-text"></span>
<span id="loader-text-status" class="loader-text">Waiting for pgAdmin 4 to start...</span>
</div>
<script type="text/javascript" src="../js/pgadmin.js"></script>
</body>
</html>
+14 -1
View File
@@ -31,6 +31,19 @@
</div>
</div>
</div>
<script type="text/javascript" src="../js/view_log.js"></script>
<script>
window.onload = async function() {
document.getElementById('status-text').innerHTML = '';
document.getElementById('server_log_label').innerHTML = 'Server Log: ' + '(' + await window.electronUI.getServerLogFile() + ')';
document.getElementById('server_log').innerHTML = await window.electronUI.readServerLog();
document.getElementById('btnReload').addEventListener('click', function() {
document.getElementById('server_log').innerHTML = 'Loading logs...';
setTimeout(async function() {
document.getElementById('server_log').innerHTML = await window.electronUI.readServerLog();
}, 500);
document.getElementById('status-text').innerHTML = 'Logs reloaded successfully';
});
}
</script>
</body>
</html>
-101
View File
@@ -1,101 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const misc = require('../js/misc.js');
// Get the window object of view log window
let gui = require('nw.gui');
let configWindow = gui.Window.get();
function checkConfiguration() {
let configData = misc.ConfigureStore.getConfigData();
if (document.getElementById('fixedPortCheck').checked && configData['portNo'] !== document.getElementById('portNo').value) {
let fixedPort = parseInt(document.getElementById('portNo').value);
// get the available TCP port
misc.getAvailablePort(fixedPort)
.then(() => {
saveConfiguration();
})
.catch(() => {
alert('The port specified is already in use. Please enter a free port number.');
});
} else {
saveConfiguration();
}
}
function saveConfiguration() {
misc.ConfigureStore.set('fixedPort', document.getElementById('fixedPortCheck').checked);
misc.ConfigureStore.set('portNo', parseInt(document.getElementById('portNo').value));
misc.ConfigureStore.set('connectionTimeout', parseInt(document.getElementById('timeOut').value));
misc.ConfigureStore.set('openDocsInBrowser', document.getElementById('openDocsInBrowser').checked);
misc.ConfigureStore.saveConfig();
document.getElementById('status-text').innerHTML = 'Configuration Saved';
if (confirm('pgAdmin 4 must be restarted for changes to take effect.\n\n Do you want to quit the application?') === true) {
misc.cleanupAndQuitApp();
}
configWindow.close();
}
function onCheckChange() {
if (this.checked) {
document.getElementById('portNo').removeAttribute('disabled');
} else {
document.getElementById('portNo').setAttribute('disabled', 'disabled');
}
// Enable/Disable Save button
enableDisableSaveButton();
}
function enableDisableSaveButton() {
let configData = misc.ConfigureStore.getConfigData();
if (configData['fixedPort'] !== document.getElementById('fixedPortCheck').checked ||
configData['portNo'] != document.getElementById('portNo').value ||
configData['connectionTimeout'] != document.getElementById('timeOut').value ||
configData['openDocsInBrowser'] !== document.getElementById('openDocsInBrowser').checked) {
document.getElementById('btnSave').removeAttribute('disabled');
} else {
document.getElementById('btnSave').setAttribute('disabled', 'disabled');
}
}
configWindow.on('loaded', function() {
document.getElementById('status-text').innerHTML = '';
// Get the config data from the file.
let configData = misc.ConfigureStore.getConfigData();
// Set the GUI value as per configuration.
if (configData['fixedPort']) {
document.getElementById('fixedPortCheck').checked = true;
document.getElementById('portNo').disabled = false;
} else {
document.getElementById('fixedPortCheck').checked = false;
document.getElementById('portNo').disabled = true;
}
document.getElementById('portNo').value = configData['portNo'];
document.getElementById('timeOut').value = configData['connectionTimeout'];
if (configData['openDocsInBrowser']) {
document.getElementById('openDocsInBrowser').checked = true;
} else {
document.getElementById('openDocsInBrowser').checked = false;
}
// Add event listeners
document.getElementById('btnSave').addEventListener('click', checkConfiguration);
document.getElementById('fixedPortCheck').addEventListener('change', onCheckChange);
document.getElementById('portNo').addEventListener('change', enableDisableSaveButton);
document.getElementById('timeOut').addEventListener('change', enableDisableSaveButton);
document.getElementById('openDocsInBrowser').addEventListener('change', enableDisableSaveButton);
});
+111
View File
@@ -0,0 +1,111 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import { app, Menu, ipcMain, BrowserWindow } from 'electron';
const isMac = process.platform == 'darwin';
const isLinux = process.platform == 'linux';
let mainMenu;
function buildMenu(pgadminMenus, pgAdminMainScreen, callbacks) {
const template = [];
// bind all menus click event.
pgadminMenus = pgadminMenus.map((menuItem)=>{
return {
...menuItem,
submenu: menuItem.submenu?.map((subMenuItem)=>{
const smName = `${menuItem.name}_${subMenuItem.name}`;
return {
...subMenuItem,
click: ()=>{
pgAdminMainScreen.webContents.send('menu-click', smName);
},
submenu: subMenuItem.submenu?.map((deeperSubMenuItem)=>{
return {
...deeperSubMenuItem,
click: ()=>{
pgAdminMainScreen.webContents.send('menu-click', `${smName}_${deeperSubMenuItem.name}`);
},
};
}),
};
}),
};
});
let menuFile = pgadminMenus.shift();
template.push({
...menuFile,
submenu: [
...menuFile.submenu,
{ type: 'separator' },
{
label: 'View Logs...', click: callbacks['view_logs'],
},
{
label: 'Configure runtime...', click: callbacks['configure'],
},
{ type: 'separator' },
...(isMac ? [
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
] : []),
{ role: 'quit' },
],
});
if(isMac) {
template[0].label = app.name;
}
// push all except help
template.push(...pgadminMenus.slice(0, -1));
template.push(
{ role: 'editMenu' },
{
label: 'View',
submenu: [
{ label: 'Reload', click: ()=>BrowserWindow.getFocusedWindow().webContents.reload()},
{ label: 'Toggle Developer Tools', click: ()=>BrowserWindow.getFocusedWindow().webContents.openDevTools({ mode: 'bottom' })},
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
].concat(isLinux ? [] : [{ role: 'togglefullscreen' }]),
},
{ role: 'windowMenu' },
);
template.push(pgadminMenus[pgadminMenus.length-1]);
return Menu.buildFromTemplate(template);
}
export function setupMenu(pgAdminMainScreen, callbacks={}) {
ipcMain.on('setMenus', (event, menus)=>{
mainMenu = buildMenu(menus, pgAdminMainScreen, callbacks);
if(isMac) {
Menu.setApplicationMenu(mainMenu);
} else {
pgAdminMainScreen.setMenu(mainMenu);
}
ipcMain.on('enable-disable-menu-items', (event, menu, menuItem)=>{
const menuItemObj = mainMenu.getMenuItemById(menuItem?.id);
if(menuItemObj) {
menuItemObj.enabled = menuItem.isDisabled;
}
});
});
}
+39 -331
View File
@@ -7,16 +7,13 @@
//
//////////////////////////////////////////////////////////////
const fs = require('fs');
const path = require('path');
const net = require('net');
const {platform, homedir} = require('os');
import fs from 'fs';
import path from 'path';
import net from 'net';
import {platform} from 'os';
import { app, session } from 'electron';
let pgadminServerProcess = null;
let pgAdminWindowObject = null;
let zoomInShortcut = null;
let zoomOutShortcut = null;
let actualSizeShortcut = null;
let toggleFullScreenShortcut = null;
// This function is used to check whether directory is present or not
// if not present then create it recursively
@@ -26,21 +23,34 @@ const createDir = (dirName) => {
}
};
const insideFlatpak = () => {
return platform() === 'linux' && fs.existsSync('/.flatpak-info');
};
// This function is used to get the python executable path
// based on the platform. Use this for deployment.
const getPythonPath = () => {
let pythonPath;
export const getAppPaths = (basePath) => {
let pythonPath, pgadminFile;
switch (platform()) {
case 'win32':
pythonPath = '../python/python.exe';
pythonPath = '../../../../../python/python.exe';
pgadminFile = '../../../../../web/pgAdmin4.py';
break;
case 'darwin':
pythonPath = '../../Frameworks/Python.framework/Versions/Current/bin/python3';
pythonPath = '../../../../Frameworks/Python.framework/Versions/Current/bin/python3';
pgadminFile = '../../../web/pgAdmin4.py';
break;
case 'linux':
pythonPath = '../venv/bin/python3';
pythonPath = '../../../../../venv/bin/python3';
pgadminFile = '../../../../../web/pgAdmin4.py';
if (insideFlatpak()) {
pythonPath = '/usr/bin/python';
pgadminFile = '/app/pgAdmin4/web/pgAdmin4.py';
return [pythonPath, pgadminFile];
}
break;
default:
pgadminFile = '../../../web/pgAdmin4.py';
if (platform().startsWith('win')) {
pythonPath = '../python/python.exe';
} else {
@@ -48,69 +58,15 @@ const getPythonPath = () => {
}
}
return pythonPath;
};
// This function is used to get the [roaming] app data path
// based on the platform. Use this for config etc.
const getAppDataPath = () => {
let appDataPath;
switch (platform()) {
case 'win32':
appDataPath = path.join(process.env.APPDATA, 'pgadmin');
break;
case 'darwin':
appDataPath = path.join(homedir(), 'Library', 'Preferences', 'pgadmin');
break;
case 'linux':
if ('XDG_CONFIG_HOME' in process.env) {
appDataPath = path.join(process.env.XDG_CONFIG_HOME, 'pgadmin');
} else {
appDataPath = path.join(homedir(), '.config', 'pgadmin');
}
break;
default:
if (platform().startsWith('win')) {
appDataPath = path.join(process.env.APPDATA, 'pgadmin');
} else if ('XDG_CONFIG_HOME' in process.env) {
appDataPath = path.join(process.env.XDG_CONFIG_HOME, 'pgadmin');
} else {
appDataPath = path.join(homedir(), '.config', 'pgadmin');
}
}
// Create directory if not exists
createDir(appDataPath);
return appDataPath;
return [path.join(basePath, pythonPath), path.join(basePath, pgadminFile)];
};
// This function is used to get the [local] app data path
// based on the platform. Use this for logs etc.
const getLocalAppDataPath = () => {
let localAppDataPath;
switch (platform()) {
case 'win32':
localAppDataPath = path.join(process.env.LOCALAPPDATA, 'pgadmin');
break;
case 'darwin':
localAppDataPath = path.join(homedir(), 'Library', 'Application Support', 'pgadmin');
break;
case 'linux':
if ('XDG_DATA_HOME' in process.env) {
localAppDataPath = path.join(process.env.XDG_DATA_HOME, 'pgadmin');
} else {
localAppDataPath = path.join(homedir(), '.local', 'share', 'pgadmin');
}
break;
default:
if (platform().startsWith('win')) {
localAppDataPath = path.join(process.env.LOCALAPPDATA, 'pgadmin');
} else if ('XDG_DATA_HOME' in process.env) {
localAppDataPath = path.join(process.env.XDG_DATA_HOME, 'pgadmin');
} else {
localAppDataPath = path.join(homedir(), '.local', 'share', 'pgadmin');
}
let localAppDataPath = app.getPath('userData');
if(process.platform == 'linux' && 'XDG_DATA_HOME' in process.env) {
localAppDataPath = path.join(process.env.XDG_DATA_HOME, app.name);
}
// Create directory if not exists
@@ -121,14 +77,14 @@ const getLocalAppDataPath = () => {
// This function is used to get the random available TCP port
// if fixedPort is set to 0. Else check whether port is in used or not.
const getAvailablePort = (fixedPort) => {
export const getAvailablePort = (fixedPort) => {
return new Promise(function(resolve, reject) {
const server = net.createServer();
server.listen(fixedPort, '127.0.0.1');
server.on('error', (e) => {
reject(e.code);
reject(e instanceof Error ? e : new Error(e.code));
});
server.on('listening', () => {
@@ -140,13 +96,10 @@ const getAvailablePort = (fixedPort) => {
};
// Get the app data folder path
const currentTime = (new Date()).getTime();
const serverLogFile = path.join(getLocalAppDataPath(), 'pgadmin4.' + currentTime.toString() + '.log');
const configFileName = path.join(getAppDataPath(), 'runtime_config.json');
const DEFAULT_CONFIG_DATA = {'fixedPort': false, 'portNo': 5050, 'connectionTimeout': 90, 'zoomLevel': 0, 'openDocsInBrowser': true};
const serverLogFile = path.join(getLocalAppDataPath(), 'pgadmin4.' + (new Date()).getTime().toString() + '.log');
// This function is used to read the file and return the content
const readServerLog = () => {
export const readServerLog = () => {
let data = null;
if (fs.existsSync(serverLogFile)) {
@@ -161,7 +114,7 @@ const readServerLog = () => {
};
// This function is used to write the data into the log file
const writeServerLog = (data) => {
export const writeServerLog = (data) => {
data = data + '\n';
if (fs.existsSync(serverLogFile)) {
fs.writeFileSync(serverLogFile, data, {flag: 'a+'});
@@ -178,28 +131,18 @@ const removeLogFile = () => {
};
// This function used to set the object of pgAdmin server process.
const setProcessObject = (processObject) => {
export const setProcessObject = (processObject) => {
pgadminServerProcess = processObject;
};
// This function used to set the object of pgAdmin window.
const setPgAdminWindowObject = (windowObject) => {
pgAdminWindowObject = windowObject;
};
// This function is used to get the server log file.
const getServerLogFile = () => {
export const getServerLogFile = () => {
return serverLogFile;
};
// This function is used to get the runtime config file.
const getRunTimeConfigFile = () => {
return configFileName;
};
// This function is used to kill the server process, remove the log files
// and quit the application.
const cleanupAndQuitApp = () => {
export const cleanupAndQuitApp = () => {
// Remove the server log file on exit
removeLogFile();
@@ -209,246 +152,11 @@ const cleanupAndQuitApp = () => {
process.kill(pgadminServerProcess.pid);
}
catch (e) {
console.warn('Failed to kill server process.');
console.warn('Failed to kill server process.', e);
}
}
if (pgAdminWindowObject != null) {
// Remove all the cookies.
pgAdminWindowObject.cookies.getAll({}, function(cookies) {
try {
cookies.forEach(function(cookie) {
pgAdminWindowObject.cookies.remove({url: 'http://' + cookie.domain, name: cookie.name});
});
} catch (error) {
console.warn('Failed to remove cookies.');
} finally {
pgAdminWindowObject = null;
// Quit Application
nw.App.quit();
}
});
} else {
// Quit Application
nw.App.quit();
}
};
// This function is used to create zoom events based on platform
const setZoomEvents = () => {
if (platform() == 'darwin') {
zoomInShortcut = new nw.Shortcut({key: 'Command+Equal'});
zoomOutShortcut = new nw.Shortcut({key: 'Command+Minus'});
actualSizeShortcut = new nw.Shortcut({key: 'Command+0'});
toggleFullScreenShortcut = new nw.Shortcut({key: 'Command+Ctrl+F'});
} else {
zoomInShortcut = new nw.Shortcut({key: 'Ctrl+Equal'});
zoomOutShortcut = new nw.Shortcut({key: 'Ctrl+Minus'});
actualSizeShortcut = new nw.Shortcut({key: 'Ctrl+0'});
// Use F10 instead of F11. F11 does not work possibly due to Chromium reserving it for their function.
toggleFullScreenShortcut = new nw.Shortcut({key: 'F10'});
}
zoomInShortcut.on('active', function() {
zoomIn();
});
zoomOutShortcut.on('active', function() {
zoomOut();
});
actualSizeShortcut.on('active', function() {
actualSize();
});
toggleFullScreenShortcut.on('active', function() {
toggleFullScreen();
});
zoomInShortcut.on('failed', function(msg) {
let errMsg = 'Failed to register zoom in shortcut with error: ' + msg;
console.warn(errMsg);
});
zoomOutShortcut.on('failed', function(msg) {
let errMsg = 'Failed to register zoom out shortcut with error: ' + msg;
console.warn(errMsg);
});
actualSizeShortcut.on('failed', function(msg) {
let errMsg = 'Failed to register actual size shortcut with error: ' + msg;
console.warn(errMsg);
});
toggleFullScreenShortcut.on('failed', function(msg) {
let errMsg = 'Failed to register toggle full screen shortcut with error: ' + msg;
console.warn(errMsg);
session.defaultSession.clearStorageData({
storages: ['cookies', 'localstorage'],
});
};
// This function is used to iterate all open windows and set the zoom level.
const setZoomLevelForAllWindows = () => {
nw.Window.getAll(function(winArray) {
for (let arr_val of winArray) {
arr_val.zoomLevel = pgAdminWindowObject.zoomLevel;
}
});
};
// This function used to zoom in the pgAdmin window.
const zoomIn = () => {
if (pgAdminWindowObject != null) {
pgAdminWindowObject.zoomLevel += 0.5;
setZoomLevelForAllWindows();
ConfigureStore.set('zoomLevel', pgAdminWindowObject.zoomLevel);
ConfigureStore.saveConfig();
}
};
// This function used to zoom out the pgAdmin window.
const zoomOut = () => {
if (pgAdminWindowObject != null) {
pgAdminWindowObject.zoomLevel -= 0.5;
setZoomLevelForAllWindows();
ConfigureStore.set('zoomLevel', pgAdminWindowObject.zoomLevel);
ConfigureStore.saveConfig();
}
};
// This function used to reset the zoom level of pgAdmin window.
const actualSize = () => {
if (pgAdminWindowObject != null) {
pgAdminWindowObject.zoomLevel = 0;
setZoomLevelForAllWindows();
ConfigureStore.set('zoomLevel', pgAdminWindowObject.zoomLevel);
ConfigureStore.saveConfig();
}
};
const toggleFullScreen = () => {
if (pgAdminWindowObject != null) {
// Toggle full screen
pgAdminWindowObject.toggleFullscreen();
// Change the menu label.
let menu_label = pgAdminWindowObject.window.document.querySelector('#mnu_toggle_fullscreen_runtime span').innerHTML;
if (menu_label.indexOf('Enter Full Screen') >= 0) {
pgAdminWindowObject.window.document.querySelector('#mnu_toggle_fullscreen_runtime span').innerHTML = menu_label.replace('Enter', 'Exit');
} else if (menu_label.indexOf('Exit Full Screen') >= 0) {
pgAdminWindowObject.window.document.querySelector('#mnu_toggle_fullscreen_runtime span').innerHTML = menu_label.replace('Exit', 'Enter');
}
}
};
// This function is used to register zoom events.
const registerZoomEvents = () => {
nw.App.registerGlobalHotKey(zoomInShortcut);
nw.App.registerGlobalHotKey(zoomOutShortcut);
nw.App.registerGlobalHotKey(actualSizeShortcut);
nw.App.registerGlobalHotKey(toggleFullScreenShortcut);
};
// This function is used to unregister zoom events.
const unregisterZoomEvents = () => {
nw.App.unregisterGlobalHotKey(zoomInShortcut);
nw.App.unregisterGlobalHotKey(zoomOutShortcut);
nw.App.unregisterGlobalHotKey(actualSizeShortcut);
nw.App.unregisterGlobalHotKey(toggleFullScreenShortcut);
};
let ConfigureStore = {
fileName: configFileName,
jsonData: {},
init: function() {
if (!this.readConfig()){
this.jsonData = DEFAULT_CONFIG_DATA;
this.saveConfig();
}
},
// This function is used to write configuration data
saveConfig: function() {
fs.writeFileSync(this.fileName, JSON.stringify(this.jsonData, null, 4), {flag: 'w'});
},
// This function is used to read the configuration data
readConfig: function() {
if (fs.existsSync(this.fileName)) {
try {
this.jsonData = JSON.parse(fs.readFileSync(this.fileName));
} catch (error) {
/* If the file is not present or invalid JSON data in file */
this.jsonData = {};
}
} else {
let errMsg = 'Unable to read file ' + this.fileName + ' not found.';
console.warn(errMsg);
return false;
}
return true;
},
getConfigData: function() {
return this.jsonData;
},
get: function(key, if_not_value) {
if(this.jsonData[key] !== undefined) {
return this.jsonData[key];
} else {
return if_not_value;
}
},
set: function(key, value) {
if(typeof key === 'object'){
this.jsonData = {
...this.jsonData,
...key,
};
} else if(value === '' || value == null || typeof(value) == 'undefined') {
if(this.jsonData[key] !== undefined) {
delete this.jsonData[key];
}
} else {
this.jsonData[key] = value;
}
},
};
function parseConsoleArgs(_method, args) {
const retData = Array.from(args).map(arg => {
try {
if(arg.stack) return arg.stack;
return JSON.stringify(arg);
} catch (e) {
return arg
}
});
return retData?.join(' ');
}
module.exports = {
readServerLog: readServerLog,
writeServerLog: writeServerLog,
getAvailablePort: getAvailablePort,
getPythonPath: getPythonPath,
setProcessObject: setProcessObject,
cleanupAndQuitApp: cleanupAndQuitApp,
getServerLogFile: getServerLogFile,
getRunTimeConfigFile: getRunTimeConfigFile,
setPgAdminWindowObject: setPgAdminWindowObject,
zoomIn: zoomIn,
zoomOut: zoomOut,
actualSize: actualSize,
toggleFullScreen: toggleFullScreen,
setZoomEvents: setZoomEvents,
registerZoomEvents: registerZoomEvents,
unregisterZoomEvents: unregisterZoomEvents,
setZoomLevelForAllWindows: setZoomLevelForAllWindows,
ConfigureStore: ConfigureStore,
parseConsoleArgs: parseConsoleArgs,
};
+21
View File
@@ -0,0 +1,21 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const { contextBridge, ipcRenderer } = require('electron/renderer');
contextBridge.exposeInMainWorld('electronUI', {
getConfigData: (key) => ipcRenderer.invoke('getStoreData', key),
setConfigData: (newValues) => ipcRenderer.invoke('setStoreData', newValues),
showMessageBox: (options) => ipcRenderer.invoke('showMessageBox', options),
restartApp: ()=>{ ipcRenderer.send('restartApp'); },
getServerLogFile: ()=>ipcRenderer.invoke('getServerLogFile'),
readServerLog: ()=>ipcRenderer.invoke('readServerLog'),
checkPortAvailable: (port)=>ipcRenderer.invoke('checkPortAvailable', port),
openConfigure: ()=>ipcRenderer.invoke('openConfigure'),
});
+248 -536
View File
@@ -6,40 +6,115 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const misc = require('../js/misc.js');
const spawn = require('child_process').spawn;
const {EOL} = require('os');
import { app, BrowserWindow, dialog, ipcMain, Menu, shell } from 'electron';
import axios from 'axios';
import Store from 'electron-store';
import fs from 'fs';
import path from 'path';
import * as misc from './misc.js';
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { setupMenu } from './menu.js';
import contextMenu from 'electron-context-menu';
const configStore = new Store({
defaults: {
fixedPort: false,
portNo: 5050,
connectionTimeout: 180,
openDocsInBrowser: true,
},
});
let pgadminServerProcess = null;
let startPageUrl = null;
let serverCheckUrl = null;
let addMenuCompleted = false;
let pgAdminMainScreen = null;
let serverPort = 5050;
let appStartTime = (new Date()).getTime();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
let docsURLSubStrings = ['www.enterprisedb.com', 'www.postgresql.org', 'www.pgadmin.org', 'help/help'];
process.env['ELECTRON_ENABLE_SECURITY_WARNINGS'] = false;
// Paths to the rest of the app
let pythonPath = misc.getPythonPath();
let pgadminFile = '../web/pgAdmin4.py';
let configFile = '../web/config.py';
let [pythonPath, pgadminFile] = misc.getAppPaths(__dirname);
// Do not allow a second instance of pgAdmin to run.
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', () => {
// Someone tried to run a second instance, we should focus our window.
if (pgAdminMainScreen) {
if (pgAdminMainScreen.isMinimized()) pgAdminMainScreen.restore();
pgAdminMainScreen.focus();
}
});
}
// Override the paths above, if a developer needs to
if (fs.existsSync('dev_config.json')) {
try {
let dev_config = JSON.parse(fs.readFileSync('dev_config.json'));
pythonPath = dev_config['pythonPath'];
pgadminFile = dev_config['pgadminFile'];
pythonPath = path.resolve(dev_config['pythonPath']);
pgadminFile = path.resolve(dev_config['pgadminFile']);
} catch (error) {
// Meh.
console.error('Failed to load dev_config', error);
}
}
contextMenu({
showInspectElement: false,
showSearchWithGoogle: false,
showLookUpSelection: false,
showSelectAll: true,
});
Menu.setApplicationMenu(null);
function openConfigure() {
const win = new BrowserWindow({
show: false,
width: 600,
height: 620,
position: 'center',
resizable: false,
icon: '../../assets/pgAdmin4.png',
webPreferences: {
preload: path.join(__dirname, 'other_preload.js'),
},
});
win.loadFile('./src/html/configure.html');
win.once('ready-to-show', ()=>{
win.show();
});
}
function showErrorDialog(intervalID) {
if(!splashWindow.isVisible()) {
return;
}
clearInterval(intervalID);
splashWindow.close();
new BrowserWindow({
'frame': true,
'width': 800,
'height': 450,
'position': 'center',
'resizable': false,
'focus': true,
'show': true,
icon: '../../assets/pgAdmin4.png',
webPreferences: {
preload: path.join(__dirname, 'other_preload.js'),
},
}).loadFile('./src/html/server_error.html');
}
// This functions is used to start the pgAdmin4 server by spawning a
// separate process.
function startDesktopMode() {
@@ -48,6 +123,7 @@ function startDesktopMode() {
if (pgadminServerProcess != null)
return;
let pingIntervalID;
let UUID = crypto.randomUUID();
// Set the environment variables so that pgAdmin 4 server
// starts listening on the appropriate port.
@@ -59,28 +135,25 @@ function startDesktopMode() {
startPageUrl = 'http://127.0.0.1:' + serverPort + '/?key=' + UUID;
serverCheckUrl = 'http://127.0.0.1:' + serverPort + '/misc/ping?key=' + UUID;
document.getElementById('loader-text-status').innerHTML = 'Starting pgAdmin 4...';
// Write Python Path, pgAdmin file path and command in log file.
misc.writeServerLog('pgAdmin Runtime Environment');
misc.writeServerLog('--------------------------------------------------------');
let command = path.resolve(pythonPath) + ' -s ' + path.resolve(pgadminFile);
misc.writeServerLog('Python Path: "' + path.resolve(pythonPath) + '"');
misc.writeServerLog('Runtime Config File: "' + path.resolve(misc.getRunTimeConfigFile()) + '"');
misc.writeServerLog('pgAdmin Config File: "' + path.resolve(configFile) + '"');
misc.writeServerLog('Webapp Path: "' + path.resolve(pgadminFile) + '"');
let command = pythonPath + ' -s ' + pgadminFile;
misc.writeServerLog('Python Path: "' + pythonPath + '"');
misc.writeServerLog('Runtime Config File: "' + path.resolve(configStore.path) + '"');
misc.writeServerLog('Webapp Path: "' + pgadminFile + '"');
misc.writeServerLog('pgAdmin Command: "' + command + '"');
misc.writeServerLog('Environment: ');
Object.keys(process.env).forEach(function (key) {
// Below code is included only for Mac OS as default path for azure CLI
// installation path is not included in PATH variable while spawning
// runtime environment.
if (platform() === 'darwin' && key === 'PATH') {
if (process.platform === 'darwin' && key === 'PATH') {
let updated_path = process.env[key] + ':/usr/local/bin';
process.env[key] = updated_path;
}
if (platform() === 'win32' && key.toUpperCase() === 'PATH') {
if (process.platform === 'win32' && key.toUpperCase() === 'PATH') {
let _libpq_path = path.join(path.dirname(path.dirname(path.resolve(pgadminFile))), 'runtime');
process.env[key] = _libpq_path + ';' + process.env[key];
}
@@ -91,12 +164,14 @@ function startDesktopMode() {
// Spawn the process to start pgAdmin4 server.
let spawnStartTime = (new Date).getTime();
pgadminServerProcess = spawn(path.resolve(pythonPath), ['-s', path.resolve(pgadminFile)]);
pgadminServerProcess = spawn(pythonPath, ['-s', pgadminFile]);
pgadminServerProcess.on('error', function (err) {
// Log the error into the log file if process failed to launch
misc.writeServerLog('Failed to launch pgAdmin4. Error:');
misc.writeServerLog(err);
showErrorDialog(pingIntervalID);
});
let spawnEndTime = (new Date).getTime();
misc.writeServerLog('Total spawn time to start the pgAdmin4 server: ' + (spawnEndTime - spawnStartTime) / 1000 + ' Sec');
@@ -116,7 +191,7 @@ function startDesktopMode() {
return axios.get(serverCheckUrl);
}
let connectionTimeout = misc.ConfigureStore.get('connectionTimeout', 90) * 1000;
let connectionTimeout = configStore.get('connectionTimeout', 180) * 1000;
let currentTime = (new Date).getTime();
let endTime = currentTime + connectionTimeout;
let midTime1 = currentTime + (connectionTimeout / 2);
@@ -125,7 +200,7 @@ function startDesktopMode() {
// ping pgAdmin server every 1 second.
let pingStartTime = (new Date).getTime();
let intervalID = setInterval(function () {
pingIntervalID = setInterval(function () {
// If ping request is already send and response is not
// received no need to send another request.
if (pingInProgress)
@@ -133,11 +208,11 @@ function startDesktopMode() {
pingServer().then(() => {
pingInProgress = false;
document.getElementById('loader-text-status').innerHTML = 'pgAdmin 4 started';
splashWindow.webContents.executeJavaScript('document.getElementById(\'loader-text-status\').innerHTML = \'pgAdmin 4 started\';', true);
// Set the pgAdmin process object to misc
misc.setProcessObject(pgadminServerProcess);
clearInterval(intervalID);
clearInterval(pingIntervalID);
let appEndTime = (new Date).getTime();
misc.writeServerLog('------------------------------------------');
misc.writeServerLog('Total time taken to ping pgAdmin4 server: ' + (appEndTime - pingStartTime) / 1000 + ' Sec');
@@ -151,33 +226,20 @@ function startDesktopMode() {
// if the connection timeout has lapsed then throw an error
// and stop pinging the server.
if (curTime >= endTime) {
clearInterval(intervalID);
splashWindow.hide();
nw.Window.open('src/html/server_error.html', {
'frame': true,
'width': 790,
'height': 430,
'position': 'center',
'resizable': false,
'focus': true,
'show': true,
});
showErrorDialog(pingIntervalID);
}
if (curTime > midTime1) {
if (curTime < midTime2) {
document.getElementById('loader-text-status').innerHTML = 'Taking longer than usual...';
splashWindow.webContents.executeJavaScript('document.getElementById(\'loader-text-status\').innerHTML = \'Taking longer than usual...\';', true);
} else {
document.getElementById('loader-text-status').innerHTML = 'Almost there...';
splashWindow.webContents.executeJavaScript('document.getElementById(\'loader-text-status\').innerHTML = \'Almost there...\';', true);
}
} else {
document.getElementById('loader-text-status').innerHTML = 'Waiting for pgAdmin 4 to start...';
}
});
pingInProgress = true;
}, 250);
}, 1000);
}
// This function is used to hide the splash screen and create/launch
@@ -185,7 +247,7 @@ function startDesktopMode() {
function launchPgAdminWindow() {
// Create and launch new window and open pgAdmin url
misc.writeServerLog('Application Server URL: ' + startPageUrl);
nw.Window.open(startPageUrl, {
pgAdminMainScreen = new BrowserWindow({
'id': 'pgadmin-main',
'icon': '../../assets/pgAdmin4.png',
'frame': true,
@@ -197,503 +259,153 @@ function launchPgAdminWindow() {
'height': 768,
'focus': true,
'show': false,
}, (pgadminWindow) => {
pgAdminMainScreen = pgadminWindow;
// Set pgAdmin4 Windows Object
misc.setPgAdminWindowObject(pgadminWindow);
// Set the zoom level stored in the config file.
pgadminWindow.zoomLevel = misc.ConfigureStore.get('zoomLevel', 0);
// Set zoom in and out events.
misc.setZoomEvents();
// Workaround to fix increasing window size.
// https://github.com/nwjs/nw.js/issues/7973
pgadminWindow.on('close', function () {
// Resize Window
resizeHeightBy = pgadminWindow.window.outerHeight - pgadminWindow.window.innerHeight;
pgadminWindow.resizeBy(0, -resizeHeightBy);
// Remove 'close' event handler, and then close window
pgadminWindow.removeAllListeners('close');
pgadminWindow.close()
});
pgadminWindow.on('closed', function () {
misc.cleanupAndQuitApp();
});
// set up handler for new-win-policy event.
// Set the width and height for the new window.
pgadminWindow.on('new-win-policy', function (frame, url, policy) {
if (!frame) {
let openDocsInBrowser = misc.ConfigureStore.get('openDocsInBrowser', true);
let isDocURL = false;
docsURLSubStrings.forEach(function (key) {
if (url.indexOf(key) >= 0) {
isDocURL = true;
}
});
if (openDocsInBrowser && isDocURL) {
// Do not open the window
policy.ignore();
// Open URL in the external browser.
nw.Shell.openExternal(url);
} else {
policy.setNewWindowManifest({
'icon': '../../assets/pgAdmin4.png',
'frame': true,
'position': 'center',
'min_width': 640,
'min_height': 480,
'width': pgadminWindow.width,
'height': pgadminWindow.height,
});
}
}
});
pgadminWindow.on('loaded', function () {
/* Make the new window opener to null as it is
* nothing but a splash screen. We will have to make it null,
* so that open in new browser tab will work.
*/
pgadminWindow.window.hookConsole((method, args)=>{
misc.writeServerLog(
`--------------[UI ${method}]---------------${EOL}${misc.parseConsoleArgs(method, args)}${EOL}------------[UI End]----------------`);
});
pgadminWindow.window.opener = null;
// Show new window
pgadminWindow.show();
pgadminWindow.focus();
nativeMenu = new gui.Menu({ type: 'menubar' });
// Create Mac Builtin Menu
if (platform() === 'darwin') {
nativeMenu.createMacBuiltin('pgAdmin 4');
// Remove 'About pgAdmin 4' submenu
nativeMenu?.items[0].submenu.removeAt(0);
// Remove 'Close Window' submenu
nativeMenu?.items[2].submenu.removeAt(1);
pgAdminMainScreen.menu = nativeMenu;
}
try {
pgAdminMainScreen.isCustomMenusAdded = false;
let addMenuInterval = setInterval(() => {
if (pgadminWindow?.window?.pgAdmin?.Browser?.Events && pgadminWindow?.window?.pgAdmin?.Browser?.MainMenus?.length > 0) {
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-enable-disable-menu-items', enableDisableMenuItem);
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-refresh-menu-item', refreshMenuItems);
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-update-checked-menu-item', updateCheckedMenuItem);
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-set-new-window-open-size', setNewWindowSize)
// Add Main Menus to native menu.
pgadminWindow.window.pgAdmin.Browser.MainMenus.forEach((menu)=> {
addMenu(menu)
})
clearInterval(addMenuInterval);
}
}, 250)
} catch (e) {
console.error('Error in add native menus');
}
// Hide the splash screen
splashWindow.hide();
});
pgadminWindow.on('blur', function () {
misc.unregisterZoomEvents();
});
pgadminWindow.on('focus', function () {
misc.registerZoomEvents();
});
});
}
// Get the gui object of NW.js
let gui = require('nw.gui');
let splashWindow = gui.Window.get();
// Enable dragging on the splash screen.
let isDragging = false;
let dragOrigin = { x: 0, y: 0 };
document.mouseleave = () => isDragging = false;
document.onmouseup = () => isDragging = false;
document.onmousedown = (e) => {
isDragging = true;
dragOrigin.x = e.x;
dragOrigin.y = e.y;
};
document.onmousemove = (e) => {
if (isDragging) {
splashWindow.moveTo(e.screenX - dragOrigin.x, e.screenY - dragOrigin.y);
}
};
// Always clear the cache before starting the application.
nw.App.clearCache();
let nativeMenu;
splashWindow.on('loaded', function () {
// Initialize the ConfigureStore
misc.ConfigureStore.init();
let fixedPortCheck = misc.ConfigureStore.get('fixedPort', false);
if (fixedPortCheck) {
serverPort = misc.ConfigureStore.get('portNo');
//Start the pgAdmin in Desktop mode.
startDesktopMode();
} else {
// get the available TCP port by sending port no to 0.
misc.getAvailablePort(0)
.then((pythonApplicationPort) => {
serverPort = pythonApplicationPort;
//Start the pgAdmin in Desktop mode.
startDesktopMode();
})
.catch((errCode) => {
if (errCode === 'EADDRINUSE') {
alert('The port specified is already in use. Please enter a free port number.');
} else {
alert(errCode);
}
});
}
});
splashWindow.on('close', function () {
misc.cleanupAndQuitApp();
});
function setNewWindowSize(){
misc.setZoomLevelForAllWindows();
}
function addCommonMenus(menu) {
let _menu = new gui.Menu();
menu.menuItems.forEach((menuItem) => {
let submenu = getSubMenu(menuItem);
let _menuItem = new gui.MenuItem({
label: menuItem.label,
enabled: !menuItem.isDisabled,
type: menuItem.type || 'normal',
priority: menuItem.priority,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
menuItem.callback();
},
});
_menu.append(_menuItem);
webPreferences: {
nodeIntegrationInSubFrames: true,
preload: path.join(__dirname, 'pgadmin_preload.js'),
},
});
if (menu.name == 'file') {
let runtimeMenu = getRuntimeMenu();
_menu.append(runtimeMenu);
}
splashWindow.close();
pgAdminMainScreen.webContents.session.clearCache();
if (menu.menuItems.length == 0) {
let _menuItem = new gui.MenuItem({
label: 'No object selected',
enabled: false,
priority: 0,
});
_menu.append(_menuItem);
}
if (platform() == 'darwin') {
pgAdminMainScreen.menu.insert(new gui.MenuItem({
label: menu.label,
name: menu.name,
submenu: _menu,
}), menu.index);
} else {
nativeMenu.append(new gui.MenuItem({
label: menu.label,
name: menu.name,
submenu: _menu,
}));
pgAdminMainScreen.menu = nativeMenu;
}
}
function getRuntimeMenu() {
let subMenus = new gui.Menu();
let rtmenudt = pgAdminMainScreen.window.pgAdmin.Browser.RUNTIME_MENUS_OPTIONS['runtime']
let runtimeSubMenus = pgAdminMainScreen.window.pgAdmin.Browser.RUNTIME_MENUS_OPTIONS['runtime']['submenus']
subMenus.append(new gui.MenuItem({
label: runtimeSubMenus['configure'].label,
enabled: runtimeSubMenus['configure'].enable,
priority: runtimeSubMenus['configure'].priority,
type: 'normal',
checked: false,
click: function () {
// Create and launch new window and open pgAdmin url
nw.Window.open('src/html/configure.html', {
'frame': true,
'width': 600,
'height': 585,
'position': 'center',
'resizable': false,
'focus': true,
'show': true,
});
},
}));
subMenus.append(new gui.MenuItem({
label: runtimeSubMenus['view_log'].label,
enabled: runtimeSubMenus['view_log'].enable,
priority: runtimeSubMenus['view_log'].priority,
type: 'normal',
checked: false,
click: function () {
// Create and launch new window and open pgAdmin url
nw.Window.open('src/html/view_log.html', {
'frame': true,
'width': 790,
'height': 425,
'position': 'center',
'resizable': false,
'focus': true,
'show': true,
});
},
}));
subMenus.append(new nw.MenuItem({ type: 'separator' }));
subMenus.append(new gui.MenuItem({
label: pgAdminMainScreen?.isFullscreen ? runtimeSubMenus['exit_full_screen'].label : runtimeSubMenus['enter_full_screen'].label,
enabled: runtimeSubMenus['enter_full_screen'].enable,
priority: runtimeSubMenus['enter_full_screen'].priority,
type: 'normal',
checked: false,
key: runtimeSubMenus['enter_full_screen'].key,
modifiers: runtimeSubMenus['enter_full_screen'].modifiers,
click: function () {
this.label = !pgAdminMainScreen?.isFullscreen ? runtimeSubMenus['exit_full_screen'].label : runtimeSubMenus['enter_full_screen'].label;
misc.toggleFullScreen();
},
}));
subMenus.append(new gui.MenuItem({
label: runtimeSubMenus['actual_size'].label,
enabled: runtimeSubMenus['actual_size'].enable,
priority: runtimeSubMenus['actual_size'].priority,
type: 'normal',
checked: false,
key: runtimeSubMenus['actual_size'].key,
modifiers: runtimeSubMenus['actual_size'].modifiers,
click: function () {
misc.actualSize();
},
}));
subMenus.append(new gui.MenuItem({
label: runtimeSubMenus['zoom_in'].label,
enabled: runtimeSubMenus['zoom_in'].enable,
priority: runtimeSubMenus['zoom_in'].priority,
type: 'normal',
checked: false,
key: runtimeSubMenus['zoom_in'].key,
modifiers: runtimeSubMenus['zoom_in'].modifiers,
click: function () {
misc.zoomIn();
},
}));
subMenus.append(new gui.MenuItem({
label: runtimeSubMenus['zoom_out'].label,
enabled: runtimeSubMenus['zoom_out'].enable,
priority: runtimeSubMenus['zoom_out'].priority,
type: 'normal',
checked: false,
key: runtimeSubMenus['zoom_out'].key,
modifiers: runtimeSubMenus['zoom_out'].modifiers,
click: function () {
misc.zoomOut();
},
}));
let runtimeMenu = new gui.MenuItem({
label: rtmenudt.label,
enabled: true,
priority: rtmenudt.priority,
type: 'normal',
checked: false,
submenu: subMenus,
})
return runtimeMenu;
}
function getSubMenu(menuItem) {
let submenu = new gui.Menu();
if (menuItem.menu_items) {
menuItem.menu_items.forEach((item) => {
let menuType = typeof item.checked == 'boolean' ? 'checkbox' : item.type;
submenu.append(new gui.MenuItem({
label: item.label,
enabled: !item.isDisabled,
priority: item.priority,
type: menuType,
checked: item.checked,
click: function () {
if (menuType == 'checkbox') {
pgAdminMainScreen.menu.items.forEach(el => {
el.submenu.items.forEach((sub) => {
if (sub.submenu?.items?.length) {
sub.submenu.items.forEach((m) => {
if (m.type == 'checkbox') {
m.label == item.label ? m.checked = true : m.checked = false;
}
});
}
});
});
}
item.callback();
setupMenu(pgAdminMainScreen, {
'view_logs': ()=>{
const win = new BrowserWindow({
show: false,
width: 800,
height: 460,
position: 'center',
resizable: false,
icon: '../../assets/pgAdmin4.png',
webPreferences: {
preload: path.join(__dirname, 'other_preload.js'),
},
}));
});
}
return submenu;
}
function addMacMenu(menu) {
if (menu.name == 'file' && platform() === 'darwin') {
let rootMenu = nativeMenu.items[0].submenu;
let indx = 0;
menu.menuItems.forEach((menuItem) => {
let submenu = getSubMenu(menuItem);
rootMenu.insert(
new gui.MenuItem({
label: menuItem.label,
type: menuItem.type || 'normal',
enabled: !menuItem.isDisabled,
priority: menuItem.priority,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
// Callback functions for actions
menuItem.callback();
},
}), indx);
indx++;
});
let runtimeMenu = getRuntimeMenu();
rootMenu.insert(runtimeMenu, indx++);
let separator_menu = new nw.MenuItem({ type: 'separator' });
rootMenu.insert(separator_menu, indx);
indx++;
pgAdminMainScreen.menu = nativeMenu;
} else {
addCommonMenus(menu)
}
}
function addOtherOsMenu(menu) {
addCommonMenus(menu)
}
function addMenu(menu) {
pgAdminMainScreen.isCustomMenusAdded = true;
if (platform() === 'darwin') {
addMacMenu(menu);
} else {
addOtherOsMenu(menu);
}
addMenuCompleted = true;
}
function enableDisableMenuItem(menu, menuItem) {
if (addMenuCompleted) {
// Enable or Disabled specific menu item
pgAdminMainScreen.menu.items.forEach(el => {
if (el?.label == menu?.label) {
el.submenu.items.forEach((sub) => {
if (sub.label == menuItem.label) {
sub.enabled = !menuItem.isDisabled;
}
});
}
});
}
}
function updateCheckedMenuItem(menuItem) {
// check/ uncheck specific menu item
pgAdminMainScreen.menu.items.forEach(el => {
el.submenu.items.forEach((sub) => {
if(sub.label == menuItem.parentMenu.label) {
sub.submenu.items.forEach((sm)=> {
if (sm.label == menuItem.label && sm.type == 'checkbox') {
sm.checked = menuItem.checked
}
})
} else if (sub.label == menuItem.label && type == 'checkbox') {
sub.checked = menuItem.checked
}
});
});
}
function refreshMenuItems(menu) {
// Add menu item/option in specific menu.
pgAdminMainScreen.menu.items.forEach(el => {
if (el.label == menu.label) {
let totalSubItems = el.submenu.items.length;
// Remove exisitng menu options to add new options.
for (let i = 0; i < totalSubItems; i++) {
el.submenu.removeAt(0);
}
menu.menuItems.forEach((item) => {
let submenu = new gui.Menu();
if (item.menu_items) {
item.menu_items.forEach((subItem) => {
submenu.append(new gui.MenuItem({
label: subItem.label,
enabled: !subItem.isDisabled,
priority: subItem.priority,
type: [true, false].includes(subItem.checked) ? 'checkbox' : 'normal',
checked: subItem.checked,
click: function () {
subItem.callback();
},
}));
});
}
let _menuItem = new gui.MenuItem({
label: item.label,
enabled: !item.isDisabled,
priority: item.priority,
type: item.type,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
item.callback();
},
});
el.submenu.append(_menuItem);
});
win.loadFile('./src/html/view_log.html');
win.once('ready-to-show', ()=>{
win.show();
});
},
'configure': openConfigure,
});
pgAdminMainScreen.loadURL(startPageUrl);
pgAdminMainScreen.setBounds(configStore.get('bounds'));
pgAdminMainScreen.show();
pgAdminMainScreen.webContents.setWindowOpenHandler(({url})=>{
let openDocsInBrowser = configStore.get('openDocsInBrowser', true);
let isDocURL = false;
docsURLSubStrings.forEach(function (key) {
if (url.indexOf(key) >= 0) {
isDocURL = true;
}
});
if (openDocsInBrowser && isDocURL) {
// Do not open the window
shell.openExternal(url);
return { action: 'deny' };
} else {
return {
action: 'allow',
overrideBrowserWindowOptions: {
'position': 'center',
'min_width': 640,
'min_height': 480,
icon: '../../assets/pgAdmin4.png',
...pgAdminMainScreen.getBounds(),
webPreferences: {
preload: path.join(__dirname, 'pgadmin_preload.js'),
},
},
};
}
});
pgAdminMainScreen.on('closed', ()=>{
misc.cleanupAndQuitApp();
});
pgAdminMainScreen.on('close', () => {
configStore.set('bounds', pgAdminMainScreen.getBounds());
pgAdminMainScreen.removeAllListeners('close');
pgAdminMainScreen.close();
});
}
let splashWindow;
// setup preload events.
ipcMain.handle('showOpenDialog', (e, options) => dialog.showOpenDialog(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('showSaveDialog', (e, options) => dialog.showSaveDialog(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('showMessageBox', (e, options) => dialog.showMessageBox(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('getStoreData', (_e, key) => key ? configStore.get(key) : configStore.store);
ipcMain.handle('setStoreData', (_e, newValues) => {
configStore.store = {
...configStore.store,
...newValues,
};
});
ipcMain.handle('getServerLogFile', () => misc.getServerLogFile());
ipcMain.handle('readServerLog', () => misc.readServerLog());
ipcMain.on('restartApp', ()=>{
app.relaunch();
app.exit(0);
});
ipcMain.handle('log', (text) => ()=>{
misc.writeServerLog(text);
});
ipcMain.handle('checkPortAvailable', async (_e, fixedPort)=>{
try {
await misc.getAvailablePort(fixedPort);
return true;
} catch {
return false;
}
});
ipcMain.handle('openConfigure', openConfigure);
app.whenReady().then(() => {
splashWindow = new BrowserWindow({
transparent: true,
width: 750,
height: 600,
frame: false,
movable: true,
focusable: true,
resizable: false,
show: false,
icon: '../../assets/pgAdmin4.png',
});
splashWindow.loadFile('./src/html/splash.html');
splashWindow.center();
splashWindow.on('show', function () {
let fixedPortCheck = configStore.get('fixedPort', false);
if (fixedPortCheck) {
serverPort = configStore.get('portNo');
//Start the pgAdmin in Desktop mode.
startDesktopMode();
} else {
// get the available TCP port by sending port no to 0.
misc.getAvailablePort(0)
.then((pythonApplicationPort) => {
serverPort = pythonApplicationPort;
//Start the pgAdmin in Desktop mode.
startDesktopMode();
})
.catch((errCode) => {
if (errCode === 'EADDRINUSE') {
dialog.showErrorBox('Error', 'The port specified is already in use. Please enter a free port number.');
} else {
dialog.showErrorBox('Error', errCode.toString());
}
splashWindow.close();
});
}
});
splashWindow.show();
});
+26
View File
@@ -0,0 +1,26 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const { contextBridge, ipcRenderer } = require('electron/renderer');
contextBridge.exposeInMainWorld('electronUI', {
onMenuClick: (callback) => ipcRenderer.on('menu-click', (_event, details) => callback(details)),
setMenus: (menus) => {
ipcRenderer.send('setMenus', menus);
},
enableDisableMenuItems: (menu, item) => {
ipcRenderer.send('enable-disable-menu-items', menu, item);
},
setMenuItems: (menu, menuItems) => {
ipcRenderer.send('set-menu-items', menu, menuItems);
},
showOpenDialog: (options) => ipcRenderer.invoke('showOpenDialog', options),
showSaveDialog: (options) => ipcRenderer.invoke('showSaveDialog', options),
log: (text)=> ipcRenderer.send('log', text),
});
-34
View File
@@ -1,34 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const misc = require('../js/misc.js');
// Get the window object of server error window
let gui = require('nw.gui');
let errorWindow = gui.Window.get();
errorWindow.on('loaded', function() {
document.getElementById('server_error_label').innerHTML = 'The pgAdmin 4 server could not be contacted:';
document.getElementById('server_error_log').innerHTML = misc.readServerLog();
document.getElementById('btnConfigure').addEventListener('click', function() {
nw.Window.open('src/html/configure.html', {
'frame': true,
'width': 600,
'height': 420,
'position': 'center',
'resizable': false,
'focus': true,
'show': true,
});
});
});
errorWindow.on('close', function() {
misc.cleanupAndQuitApp();
});
-27
View File
@@ -1,27 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const misc = require('../js/misc.js');
// Get the window object of view log window
let gui = require('nw.gui');
let logWindow = gui.Window.get();
logWindow.on('loaded', function() {
document.getElementById('status-text').innerHTML = '';
document.getElementById('server_log_label').innerHTML = 'Server Log: ' + '(' + misc.getServerLogFile() + ')';
document.getElementById('server_log').innerHTML = misc.readServerLog();
document.getElementById('btnReload').addEventListener('click', function() {
document.getElementById('server_log').innerHTML = 'Loading logs...';
setTimeout(function() {
document.getElementById('server_log').innerHTML = misc.readServerLog();
}, 500);
document.getElementById('status-text').innerHTML = 'Logs reloaded successfully';
});
});
+837 -858
View File
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -199,9 +199,9 @@ def dump_header():
def dump_runtime():
print_title("Runtime Dependencies")
print_table_header()
print_row("Python", "3.6+", "PSF", "https://www.python.org/")
print_row("nw", "0.50.2", "MIT",
"git://github.com/nwjs/npm-installer.git")
print_row("Python", "3.8+", "PSF", "https://www.python.org/")
print_row("Electron", "30.0.5", "MIT",
"https://www.npmjs.com/package/electron")
# Make sure to change the count of hardcoded_deps if we will
# manually add some more dependencies in future.
+2 -1
View File
@@ -1,5 +1,6 @@
requests>=2.21.0
requests[security]>=2.21.0
safety>=1.9.0
Sphinx==7.3.7
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
Sphinx==6.1.3
sphinxcontrib-youtube==1.4.1
-7
View File
@@ -1,7 +0,0 @@
generated
node_modules
vendor
templates/
templates\
ycache
regression/htmlcov
+111 -87
View File
@@ -6,98 +6,122 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const globals = require('globals');
const js = require('@eslint/js');
const reactjs = require('eslint-plugin-react');
const jest = require('eslint-plugin-jest');
const babel = require('@babel/eslint-plugin');
const babelParser = require('@babel/eslint-parser');
const ts = require('typescript-eslint');
module.exports = {
'env': {
'browser': true,
'es6': true,
'amd': true,
module.exports = [
{
ignores: [
'**/generated',
'**/node_modules',
'**/vendor',
'**/templates/',
'**/templates\\',
'**/ycache',
'**/regression/htmlcov',
],
},
'extends': [
'eslint:recommended',
'plugin:react/recommended',
/* Uncomment the below line to use linter error for React Hooks.
By Default commented so that builds are generated successfully.
Once all the errors will be resolved will uncomment it and commit it.
*/
// "plugin:react-hooks/recommended",
],
'parser': '@babel/eslint-parser',
'parserOptions': {
'requireConfigFile': false,
'ecmaVersion': 2018,
'ecmaFeatures': {
'jsx': true,
js.configs.recommended,
{
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
languageOptions: {
'parser': babelParser,
ecmaVersion: 2018,
parserOptions: {
'ecmaFeatures': {
'jsx': true,
},
'requireConfigFile': false,
'babelOptions': {
'plugins': [
'@babel/plugin-syntax-jsx',
'@babel/plugin-proposal-class-properties',
],
},
},
'sourceType': 'module',
globals: {
...globals.browser,
...globals.es2017,
...globals.amd,
'_': 'readonly',
'module': 'readonly',
'__dirname': 'readonly',
'global': 'readonly',
'jest': 'readonly',
'process': 'readonly',
},
},
'sourceType': 'module',
'babelOptions': {
'plugins': [
'@babel/plugin-syntax-jsx',
'@babel/plugin-proposal-class-properties',
'plugins': {
'react': reactjs,
'@babel': babel,
},
'rules': {
'indent': [
'error',
2,
],
},
},
'plugins': [
'react',
'@babel',
'jest'
],
'overrides': [
{
'files': ['**/*.{ts,tsx}'],
'plugins': [
'@typescript-eslint',
'linebreak-style': 0,
'quotes': [
'error',
'single',
],
'extends': ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/eslint-recommended'],
'parser': '@typescript-eslint/parser',
'rules': {
'@typescript-eslint/no-explicit-any': ['off'],
'@typescript-eslint/no-this-alias': ['off'],
}
'semi': [
'error',
'always',
],
'comma-dangle': [
'error',
'only-multiline',
],
'no-console': ['error', { allow: ['warn', 'error'] }],
// We need to exclude below for RegEx case
'no-useless-escape': 'off',
'no-prototype-builtins': 'off',
'no-global-assign': 'off',
'no-import-assign': 'off',
'react/jsx-uses-vars': 'error',
'react/jsx-uses-react': 'error'
},
{
'files': ['**/*{spec,test}.{js,jsx}', './regression/javascript/**/*.{js}'],
'extends': ['eslint:recommended'],
'env': {
'jest': true
}
},
],
'globals': {
'_': true,
'module': true,
'__dirname': true,
'global': true,
'jest': true
},
'rules': {
'indent': [
'error',
2,
],
'linebreak-style': 0,
'quotes': [
'error',
'single',
],
'semi': [
'error',
'always',
],
'comma-dangle': [
'error',
'only-multiline',
],
'no-console': ['error', { allow: ['warn', 'error'] }],
// We need to exclude below for RegEx case
'no-useless-escape': 0,
'no-prototype-builtins': 0,
'no-global-assign': 0,
'no-import-assign': 0,
},
'settings': {
'react': {
'version': 'detect',
'settings': {
'react': {
'version': 'detect',
},
},
},
};
{
'files': ['**/*.{ts,tsx}'],
languageOptions: {
'parser': ts.parser,
},
'plugins': {
'@typescript-eslint': ts.plugin,
},
'rules': {
'no-unused-vars': 'off',
'no-undef': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'@typescript-eslint/no-explicit-any': ['off'],
'@typescript-eslint/no-this-alias': ['off'],
}
},
{
'files': ['**/*{spec,test}.{js,jsx}', './regression/javascript/**/*.{js}'],
...jest.configs['flat/recommended'],
rules: {
...jest.configs['flat/recommended'].rules,
'jest/prefer-expect-assertions': 'off',
'jest/expect-expect': 'off',
'jest/no-identical-title': 'off',
'jest/no-done-callback': 'off',
'jest/no-conditional-expect': 'off',
'jest/valid-title': 'off',
},
}
];
+12 -2
View File
@@ -461,12 +461,14 @@ DEFAULT_BINARY_PATHS = {
"pg-14": "",
"pg-15": "",
"pg-16": "",
"pg-17": "",
"ppas": "",
"ppas-12": "",
"ppas-13": "",
"ppas-14": "",
"ppas-15": "",
"ppas-16": ""
"ppas-16": "",
"ppas-17": ""
}
##########################################################################
@@ -481,12 +483,14 @@ FIXED_BINARY_PATHS = {
"pg-14": "",
"pg-15": "",
"pg-16": "",
"pg-17": "",
"ppas": "",
"ppas-12": "",
"ppas-13": "",
"ppas-14": "",
"ppas-15": "",
"ppas-16": ""
"ppas-16": "",
"ppas-17": ""
}
##########################################################################
@@ -925,6 +929,12 @@ SERVER_HEARTBEAT_TIMEOUT = 30 # In seconds
#############################################################################
ENABLE_SERVER_PASS_EXEC_CMD = False
#############################################################################
# Number of records to fetch in one batch for server logs.
##############################################################################
ON_DEMAND_LOG_COUNT = 10000
#############################################################################
# Patch the default config with custom config and other manipulations
#############################################################################
+5 -3
View File
@@ -8,8 +8,8 @@ Create Date: 2024-05-17 19:35:03.700104
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.orm.session import Session
from pgadmin.model import Preferences
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'ac2c2e27dc2d'
@@ -19,9 +19,11 @@ depends_on = None
def upgrade():
db.session.query(Preferences).filter(
session = Session(bind=op.get_bind())
session.query(Preferences).filter(
Preferences.name == 'execute_query').update({'name': 'execute_script'})
db.session.commit()
session.commit()
meta = sa.MetaData()
meta.reflect(op.get_bind(), only=('user_macros',))
+48 -52
View File
@@ -8,141 +8,138 @@
"license": "PostgreSQL",
"devDependencies": {
"@babel/core": "^7.10.2",
"@babel/eslint-parser": "^7.21.3",
"@babel/eslint-plugin": "^7.17.7",
"@babel/eslint-parser": "^7.24.7",
"@babel/eslint-plugin": "^7.24.7",
"@babel/plugin-proposal-object-rest-spread": "^7.10.1",
"@babel/plugin-syntax-jsx": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.22.15",
"@babel/preset-env": "^7.10.2",
"@babel/preset-typescript": "^7.22.5",
"@emotion/core": "^10.0.14",
"@babel/preset-typescript": "^7.24.7",
"@emotion/memoize": "^0.7.5",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@emotion/utils": "^1.0.0",
"@svgr/webpack": "^8.1.0",
"@testing-library/jest-dom": "^6.1.2",
"@testing-library/react": "12",
"@testing-library/user-event": "^14.4.3",
"@testing-library/dom": "10.2.0",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.4",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.57.0",
"autoprefixer": "^10.2.4",
"axios-mock-adapter": "^1.17.0",
"babel-loader": "^8.1.0",
"babel-loader": "^9.1.3",
"browserify": "^17.0.0",
"buffer": "^6.0.3",
"copy-webpack-plugin": "^11.0.0",
"copy-webpack-plugin": "^12.0.2",
"cross-env": "^7.0.3",
"css-loader": "^6.7.2",
"css-minimizer-webpack-plugin": "^5.0.0",
"eslint": "^8.37.0",
"eslint": "^9.8.0",
"eslint-plugin-jest": "^27.4.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react-hooks": "^4.3.0",
"exports-loader": "^4.0.0",
"globals": "^15.8.0",
"html-react-parser": "^5.0.6",
"image-minimizer-webpack-plugin": "^3.8.2",
"image-minimizer-webpack-plugin": "^4.0.2",
"imagemin": "^8.0.1",
"imagemin-mozjpeg": "^10.0.0",
"imagemin-optipng": "^8.0.0",
"imports-loader": "^4.0.1",
"is-docker": "^2.1.1",
"jest": "^29.6.4",
"jest-environment-jsdom": "^29.6.4",
"loader-utils": "^3.2.1",
"mini-css-extract-plugin": "^2.7.6",
"postcss-loader": "^7.1.0",
"postcss-loader": "^8.1.1",
"process": "^0.11.10",
"prop-types": "^15.7.2",
"resize-observer-polyfill": "^1.5.1",
"shim-loader": "^1.0.1",
"style-loader": "^3.3.2",
"stylis": "^4.0.7",
"svgo": "^2.7.0",
"svgo-loader": "^2.2.0",
"svgo": "^3.3.2",
"svgo-loader": "^4.0.0",
"terser-webpack-plugin": "^5.1.1",
"typescript": "^4.9.5",
"typescript": "^5.4.5",
"typescript-eslint": "^7.15.0",
"url-loader": "^4.1.1",
"webfonts-loader": "^8.0.1",
"webpack": "^5.88.2",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^4.5.0",
"webpack-cli": "^5.1.4",
"yarn-audit-html": "4.0.0"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-react": "^7.12.13",
"@codemirror/lang-sql": "^6.6.3",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.6.5",
"@date-io/core": "^3.0.0",
"@date-io/date-fns": "3.x",
"@emotion/sheet": "^1.0.1",
"@fortawesome/fontawesome-free": "latest",
"@mui/icons-material": "^5.15.10",
"@mui/icons-material": "^5.16.6",
"@mui/lab": "^5.0.0-alpha.165",
"@mui/material": "^5.15.10",
"@mui/styles": "^5.15.10",
"@mui/x-date-pickers": "^6.19.7",
"@projectstorm/react-diagrams": "^6.6.1",
"@mui/x-date-pickers": "^7.7.1",
"@projectstorm/react-diagrams": "^7.0.4",
"@simonwep/pickr": "^1.5.1",
"@szhsin/react-menu": "^2.2.0",
"@tanstack/react-query": "5.37.1",
"@tanstack/react-table": "^8.16.0",
"@tanstack/react-virtual": "^3.4.0",
"@tanstack/react-virtual": "^3.8.4",
"@types/classnames": "^2.2.6",
"@types/react": "^17.0.80",
"@types/react-dom": "^17.0.25",
"@types/react": "^18.0.2",
"@types/react-dom": "^18.0.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-search": "^0.15.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
"ajv": "^8.8.2",
"anti-trojan-source": "^1.4.0",
"aspen-decorations": "^1.0.2",
"axios": "^1.6.8",
"axios": "^1.7.4",
"babelify": "~10.0.0",
"bignumber.js": "^9.0.1",
"brace": "^0.11.1",
"browserfs": "^1.4.3",
"chart.js": "^3.0.0",
"chartjs-plugin-zoom": "^2.0.1",
"classnames": "^2.2.6",
"closest": "^0.0.1",
"codemirror": "^6.0.1",
"convert-units": "^2.3.4",
"cssnano": "^5.0.2",
"dagre": "^0.8.4",
"date-fns": "^3.6.0",
"diff-arrays-of-objects": "^1.1.8",
"hotkeys-js": "^3.13.3",
"html-to-image": "^1.11.11",
"immutability-helper": "^3.0.0",
"insert-if": "^1.1.0",
"ip-address": "^7.1.0",
"ip-address": "^9.0.5",
"json-bignumber": "^1.0.1",
"jsoneditor": "^9.5.4",
"leaflet": "^1.5.1",
"leaflet": "^1.9.4",
"lodash": "4.*",
"ml-matrix": "^6.5.0",
"moment": "^2.29.4",
"moment-timezone": "^0.5.34",
"notificar": "^1.0.1",
"notistack": "^2.0.8",
"notistack": "^3.0.1",
"path-fx": "^2.0.0",
"pathfinding": "^0.4.18",
"paths-js": "^0.4.9",
"postcss": "^8.4.31",
"raf": "^3.4.1",
"rc-dock": "^3.2.9",
"react": "^17.0.1",
"react": "^18.2.0",
"react-arborist": "^3.2.0",
"react-aspen": "^1.1.0",
"react-checkbox-tree": "^1.7.2",
"react-data-grid": "https://github.com/pgadmin-org/react-data-grid.git#200d2f5e02de694e3e9ffbe177c279bc40240fb8",
"react-data-grid": "https://github.com/pgadmin-org/react-data-grid.git#4e10a5a327ff58198ac83c7b0c62549b20b78ae5",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^17.0.1",
"react-dom": "^18.2.0",
"react-draggable": "^4.4.6",
"react-dropzone": "^14.2.1",
"react-frame-component": "^5.2.6",
"react-leaflet": "^3.2.2",
"react-leaflet": "^4.2.1",
"react-new-window": "^1.0.1",
"react-resize-detector": "^9.1.0",
"react-resize-detector": "^11.0.1",
"react-rnd": "^10.3.5",
"react-select": "^5.7.2",
"react-timer-hook": "^3.0.5",
@@ -156,20 +153,16 @@
"uplot-react": "^1.1.4",
"valid-filename": "^2.0.1",
"wkx": "^0.5.0",
"xterm": "^4.11.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.0",
"xterm-addon-web-links": "^0.4.0",
"zustand": "^4.4.1"
},
"scripts": {
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js --ext .jsx --ext .ts --ext .tsx .",
"linter": "yarn run eslint -c .eslintrc.js .",
"webpacker": "yarn run webpack --config webpack.config.js --progress",
"webpacker:watch": "yarn run webpack --config webpack.config.js --progress --watch",
"bundle:watch": "yarn run linter && yarn run webpacker:watch",
"bundle:dev": "yarn run linter && yarn run webpacker",
"bundle:analyze": "cross-env NODE_ENV=production ANALYZE=true yarn run bundle:dev",
"bundle": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=3072 yarn run bundle:dev",
"bundle": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=3072 yarn run bundle:dev && git log -1 --format=\"%H %as\" > commit_hash",
"test:js-once": "yarn run linter && yarn run jest --maxWorkers=50%",
"test:js": "yarn run test:js-once --watch",
"test:js-file": "yarn run test:js-once -t",
@@ -180,7 +173,10 @@
"auditjs-html": "yarn audit --json | yarn run yarn-audit-html --output ../auditjs.html",
"auditjs": "yarn audit --groups dependencies",
"auditpy": "safety check --full-report -i 51668 -i 52495",
"audit": "yarn run auditjs && yarn run auditpy"
"audit-all": "yarn run auditjs && yarn run auditpy"
},
"packageManager": "yarn@3.6.4"
"packageManager": "yarn@3.8.3",
"browserslist": [
"defaults and fully supports es6-module"
]
}
+12 -2
View File
@@ -15,8 +15,8 @@ import sys
if sys.version_info <= (3, 9):
import select
if sys.version_info < (3, 4):
raise RuntimeError('This application must be run under Python 3.4 '
if sys.version_info < (3, 8):
raise RuntimeError('This application must be run under Python 3.8 '
'or later.')
import builtins
import os
@@ -103,6 +103,16 @@ if not os.path.isfile(config.SQLITE_PATH):
app = create_app()
app.config['sessions'] = dict()
# We load the file here instead of evaluate config
# as we don't know the path of this file in evaluate config
# commit_hash file resides in the web directory
try:
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)),
'commit_hash')) as f:
config.COMMIT_HASH = f.readline().strip()
except FileNotFoundError as _:
config.COMMIT_HASH = None
if setup_db_required:
setup.setup_db(app)
+2 -2
View File
@@ -10,8 +10,8 @@
import os
import sys
if sys.version_info < (3, 4):
raise Exception('This application must be run under Python 3.4 or later.')
if sys.version_info < (3, 8):
raise Exception('This application must be run under Python 3.8 or later.')
import builtins
+4 -3
View File
@@ -16,6 +16,7 @@ import ipaddress
def get_my_ip():
""" Return the public IP of this host """
http = urllib3.PoolManager()
IP_ADDRESS_STRING = '{}/{}'
try:
external_ip = http.request('GET', 'https://ident.me').data
except Exception:
@@ -29,11 +30,11 @@ def get_my_ip():
ip = ipaddress.ip_address(external_ip)
if isinstance(ip, ipaddress.IPv4Address):
return '{}/{}'.format(external_ip, 32)
return IP_ADDRESS_STRING.format(external_ip, 32)
elif isinstance(ip, ipaddress.IPv6Address):
return '{}/{}'.format(external_ip, 128)
return IP_ADDRESS_STRING.format(external_ip, 128)
return '{}/{}'.format(external_ip, 32)
return IP_ADDRESS_STRING.format(external_ip, 32)
def get_random_id():
+3 -7
View File
@@ -520,13 +520,9 @@ def create_app(app_name=None):
security.init_app(app, user_datastore)
# register custom unauthorised handler.
if sys.version_info < (3, 8):
app.login_manager.unauthorized_handler(pga_unauthorised)
else:
# Flask-Security-Too > 5.4.* requires custom unauth handeler
# to be registeres with it.
security.unauthn_handler(pga_unauthorised)
# Flask-Security-Too > 5.4.* requires custom unauth handeler
# to be registeres with it.
security.unauthn_handler(pga_unauthorised)
# Set the permanent session lifetime to the specified value in config file.
app.permanent_session_lifetime = timedelta(
+26 -28
View File
@@ -18,10 +18,10 @@ from pgadmin.utils.menu import MenuItem
from pgadmin.utils.constants import MIMETYPE_APP_JS
from pgadmin.utils.ajax import make_json_response
import config
import httpagentparser
from pgadmin.model import User
from user_agents import parse
import platform
import re
MODULE_NAME = 'about'
@@ -59,17 +59,18 @@ def index():
"""Render the about box."""
info = {}
# Get OS , NW.js, Browser details
browser, os_details, nwjs_version = detect_browser(request)
browser, os_details, electron_version = detect_browser(request)
admin = is_admin(current_user.email)
if nwjs_version:
info['nwjs'] = nwjs_version
if electron_version:
info['electron'] = electron_version
if config.SERVER_MODE:
info['app_mode'] = gettext('Server')
else:
info['app_mode'] = gettext('Desktop')
info['commit_hash'] = getattr(config, 'COMMIT_HASH', None)
info['browser_details'] = browser
info['version'] = config.APP_VERSION
info['admin'] = admin
@@ -118,32 +119,29 @@ def is_admin(load_user):
def detect_browser(request):
"""This function returns the browser and os details"""
nwjs_version = None
electron_version = None
agent = request.environ.get('HTTP_USER_AGENT')
os_details = parse(platform.platform()).ua_string
if 'Nwjs' in agent:
agent = agent.split('-')
nwjs_version = agent[0].split(':')[1]
browser = 'Chromium' + ' ' + agent[2]
try:
# available only for python 3.10 and above
os_release = platform.freedesktop_os_release()
os_details = os_release.get('PRETTY_NAME', '')
if os_details:
os_details += ', '
except Exception as _:
os_details = ''
os_details += parse(platform.platform()).ua_string
if 'Electron' in agent:
electron_version = re.findall('Electron/([\\d.]+\\d+)', agent)[0]
browser = re.findall(
'(opera|chrome|safari|firefox|msie|trident(?=/))/?\\s*([\\d.]+\\d+)',
agent, re.IGNORECASE)
if not browser:
browser = agent.split('/')[0]
else:
browser = httpagentparser.detect(agent)
if not browser:
browser = agent.split('/')[0]
else:
browser = browser['browser']['name'] + ' ' + browser['browser'][
'version']
browser = " ".join(browser[0])
return browser, os_details, nwjs_version
@blueprint.route("/about.js")
@pga_login_required
def script():
"""render the required javascript"""
return Response(
response=render_template("about/about.js", _=gettext),
status=200,
mimetype=MIMETYPE_APP_JS
)
return browser, os_details, electron_version
+25 -40
View File
@@ -11,38 +11,13 @@ import gettext from 'sources/gettext';
import url_for from 'sources/url_for';
import React, { useEffect, useState, useRef } from 'react';
import { Box, Grid, InputLabel } from '@mui/material';
import { DefaultButton } from '../../../static/js/components/Buttons';
import { makeStyles } from '@mui/styles';
import { InputText } from '../../../static/js/components/FormComponents';
import { InputSQL } from '../../../static/js/components/FormComponents';
import getApiInstance from '../../../static/js/api_instance';
import { copyToClipboard } from '../../../static/js/clipboard';
import { useDelayedCaller } from '../../../static/js/custom_hooks';
import { usePgAdmin } from '../../../static/js/BrowserComponent';
const useStyles = makeStyles((theme)=>({
container: {
padding: '16px',
height: '100%',
display: 'flex',
flexDirection: 'column',
},
copyBtn: {
marginRight: '1px',
float: 'right',
borderColor: theme.otherVars.borderColor,
fontSize: '13px',
},
}));
export default function AboutComponent() {
const classes = useStyles();
const containerRef = useRef();
const [aboutData, setAboutData] = useState([]);
const [copyText, setCopyText] = useState(gettext('Copy'));
const revertCopiedText = useDelayedCaller(()=>{
setCopyText(gettext('Copy'));
});
const pgAdmin = usePgAdmin();
useEffect(() => {
@@ -57,7 +32,7 @@ export default function AboutComponent() {
}, []);
return (
<Box className={classes.container} ref={containerRef}>
<Box sx={{ padding: '16px', height: '100%', display: 'flex',flexDirection: 'column'}} ref={containerRef}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Version')}</InputLabel>
@@ -74,6 +49,14 @@ export default function AboutComponent() {
<InputLabel>{aboutData.app_mode}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Commit:')}</InputLabel>
</Grid>
<Grid item lg={9} md={9} sm={9} xs={12}>
<InputLabel>{aboutData.commit_hash}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Current User')}</InputLabel>
@@ -82,13 +65,13 @@ export default function AboutComponent() {
<InputLabel>{aboutData.current_user}</InputLabel>
</Grid>
</Grid>
{ aboutData.nwjs &&
{ aboutData.electron &&
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('NW.js Version')}</InputLabel>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Electron Version')}</InputLabel>
</Grid>
<Grid item lg={9} md={9} sm={9} xs={12}>
<InputLabel>{aboutData.nwjs}</InputLabel>
<InputLabel>{aboutData.electron}</InputLabel>
</Grid>
</Grid>
}
@@ -131,18 +114,20 @@ export default function AboutComponent() {
</Grid>
}
{ aboutData.settings &&
<Box flexGrow="1" display="flex" flexDirection="column">
<Box flexGrow="1" display="flex" flexDirection="column" minHeight="0">
<Box>
<span style={{fontWeight: 'bold'}}>{gettext('Server Configuration')}</span>
<DefaultButton className={classes.copyBtn} onClick={()=>{
copyToClipboard(aboutData.settings);
setCopyText(gettext('Copied!'));
revertCopiedText(1500);
}}>{copyText}</DefaultButton>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('pgAdmin Server Configuration')}</InputLabel>
</Box>
<Box flexGrow="1" paddingTop="1px">
<InputText style={{height: '100%'}} controlProps={{multiline: true, rows: 8}} inputStyle={{resize: 'none'}}
value={aboutData.settings}/>
<Box flexGrow="1" paddingTop="1px" minHeight="0">
<InputSQL value={aboutData.settings}
controlProps={{
readonly: true,
showCopyBtn: true,
}}
options={{
lineNumbers: false,
foldGutter: false
}} />
</Box>
</Box>
}
+1 -1
View File
@@ -41,7 +41,7 @@ class BaseAuthentication(metaclass=AuthSourceRegistry):
pass
@abstractmethod
def authenticate(self):
def authenticate(self, form):
pass
def validate(self, form):
-1
View File
@@ -27,7 +27,6 @@ from pgadmin.utils.constants import KERBEROS, MessageType
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response, internal_server_error
from pgadmin.authenticate.internal import BaseAuthentication
from pgadmin.authenticate import get_auth_sources
from pgadmin.utils.csrf import pgCSRFProtect
+3 -3
View File
@@ -275,6 +275,6 @@ class OAuth2Authentication(BaseAuthentication):
authorized_claims = [authorized_claims]
if any(item in authorized_claims for item in claim):
reason = "Claim match found. Authorized access."
return (True, reason)
reason = f"No match was found."
return (False, reason)
return True, reason
reason = "No match was found."
return False, reason
+8 -14
View File
@@ -65,13 +65,7 @@ from pgadmin.authenticate import AuthSourceManager
from pgadmin.utils.exception import CryptKeyMissing
from pgadmin.user_login_check import pga_login_required
try:
from flask_security.views import default_render_json
except ImportError as e:
# Support Flask-Security-Too == 3.2
if sys.version_info < (3, 8):
from flask_security.views import _render_json as default_render_json
from flask_security.views import default_render_json
MODULE_NAME = 'browser'
BROWSER_STATIC = 'browser.static'
@@ -481,10 +475,6 @@ def utils():
pg_help_path_pref = prefs.preference('pg_help_path')
pg_help_path = pg_help_path_pref.get()
# Added to have theme value available at app start page loading
prefs = Preferences.module('misc')
theme = prefs.preference('theme').get()
# Get sqleditor options
prefs = Preferences.module('sqleditor')
@@ -500,6 +490,11 @@ def utils():
brace_matching_pref = prefs.preference('brace_matching')
brace_matching = brace_matching_pref.get()
highlight_selection_matches_pref = prefs.preference(
'highlight_selection_matches'
)
highlight_selection_matches = highlight_selection_matches_pref.get()
insert_pair_brackets_perf = prefs.preference('insert_pair_brackets')
insert_pair_brackets = insert_pair_brackets_perf.get()
@@ -546,13 +541,13 @@ def utils():
render_template(
'browser/js/utils.js',
layout=layout,
theme=theme,
jssnippets=snippets,
pg_help_path=pg_help_path,
editor_tab_size=editor_tab_size,
editor_use_spaces=editor_use_spaces,
editor_wrap_code=editor_wrap_code,
editor_brace_matching=brace_matching,
editor_highlight_selection_matches=highlight_selection_matches,
editor_insert_pair_brackets=insert_pair_brackets,
editor_indent_with_tabs=editor_indent_with_tabs,
app_name=config.APP_NAME,
@@ -1108,8 +1103,7 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
form_class = _security.forms.get('reset_password_form').cls
form = form_class(request.form) if request.form else form_class()
if sys.version_info >= (3, 8):
form.user = user
form.user = user
if form.validate_on_submit():
try:
@@ -156,6 +156,21 @@ def register_browser_preferences(self):
fields=fields
)
self.preference.register(
'keyboard_shortcuts',
'close_tab_panel',
gettext('Close tab panel'),
'keyboardshortcut',
{
'alt': False,
'shift': True,
'control': True,
'key': {'key_code': 87, 'char': 'w'}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=fields
)
self.preference.register(
'keyboard_shortcuts',
'tabbed_panel_forward',
@@ -428,7 +443,7 @@ def register_browser_preferences(self):
)
)
ope_new_tab_options = [
open_new_tab_options = [
{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
@@ -436,14 +451,14 @@ def register_browser_preferences(self):
# Allow psq tool to open in new browser tab if ENABLE_PSQL is set to True
if config.ENABLE_PSQL:
ope_new_tab_options.append(
open_new_tab_options.append(
{'label': gettext('PSQL Tool'), 'value': 'psql_tool'})
self.open_in_new_tab = self.preference.register(
'tab_settings', 'new_browser_tab_open',
gettext("Open in new browser tab"), 'select', None,
category_label=PREF_LABEL_OPTIONS,
options=ope_new_tab_options,
options=open_new_tab_options,
help_str=gettext(
'Select Query Tool, Debugger, Schema Diff, ERD Tool '
'or PSQL Tool from the drop-down to set '
@@ -165,6 +165,7 @@ class ServerModule(sg.ServerGroupPluginModule):
server.tunnel_username = sharedserver.tunnel_username
server.tunnel_password = sharedserver.tunnel_password
server.save_password = sharedserver.save_password
server.tunnel_identity_file = sharedserver.tunnel_identity_file
if hasattr(server, 'connection_params') and \
hasattr(sharedserver, 'connection_params') and \
'passfile' in server.connection_params and \
@@ -1615,6 +1616,11 @@ class ServerNode(PGChildNodeView):
KEY_RING_SERVICE_NAME,
KEY_RING_USERNAME_FORMAT.format(server.name,
server.id))
prompt_password = (
True
if password is None and server.passexec_cmd is None
else False
)
else:
password = data['password'] if 'password' in data else None
save_password = data['save_password']\
@@ -35,6 +35,7 @@ from pgadmin.tools.sqleditor.utils.query_history import QueryHistory
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
from pgadmin.model import db, Server, Database
from pgadmin.browser.utils import underscore_escape
from pgadmin.utils.constants import TWO_PARAM_STRING
class DatabaseModule(CollectionNodeModule):
@@ -586,7 +587,7 @@ class DatabaseView(PGChildNodeView):
'icon': 'pg-icon-database',
'already_connected': already_connected,
'connected': True,
'info_prefix': '{0}/{1}'.
'info_prefix': TWO_PARAM_STRING.
format(Server.query.filter_by(id=sid)[0].name, conn.db)
}
)
@@ -609,7 +610,7 @@ class DatabaseView(PGChildNodeView):
data={
'icon': 'icon-database-not-connected',
'connected': False,
'info_prefix': '{0}/{1}'.
'info_prefix': TWO_PARAM_STRING.
format(Server.query.filter_by(id=sid)[0].name, conn.db)
}
)
@@ -91,7 +91,7 @@ define('pgadmin.node.cast', [
resolve(data);
})
.catch((err)=>{
reject(err);
reject(err instanceof Error ? err : Error(gettext('Something went wrong')));
});
} else {
data = [];
@@ -207,7 +207,10 @@ export default class PublicationSchema extends BaseUISchema {
state.only_table = false;
return true;
}
if (!_.isUndefined(table) && table.length > 0 && !_.isEqual(this._origData.pubtable, state.pubtable)){
if (
!_.isUndefined(table) && table.length > 0 &&
!_.isEqual(this.origData.pubtable, state.pubtable)
){
return false;
}
state.only_table = false;
@@ -304,4 +307,4 @@ export default class PublicationSchema extends BaseUISchema {
},
];
}
}
}
@@ -4,4 +4,4 @@ FROM
pg_attribute
WHERE
attrelid = '{{ tid }}' :: regclass
and attstattarget =-1;
and attnum > 0;
@@ -4,4 +4,4 @@ FROM
pg_attribute
WHERE
attrelid = '{{ tid }}' :: regclass
and attstattarget =-1;
and attnum > 0;
@@ -165,9 +165,8 @@ export default class CollationSchema extends BaseUISchema {
else {
if (actionObj.oldState.is_deterministic) {
return { is_deterministic: false };
} else {
return { is_deterministic: true };
}
return { is_deterministic: true };
}
},
},
@@ -0,0 +1,10 @@
SELECT c.oid, c.collname AS name, COALESCE(c.collcollate, c.colllocale) AS lc_collate,
COALESCE(c.collctype, c.colllocale) AS lc_type, c.collisdeterministic AS is_deterministic, c.collversion AS version,
c.collprovider AS provider, c.collicurules AS rules,
pg_catalog.pg_get_userbyid(c.collowner) AS owner, description, n.nspname AS schema
FROM pg_catalog.pg_collation c
JOIN pg_catalog.pg_namespace n ON n.oid=c.collnamespace
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=c.oid AND des.classoid='pg_collation'::regclass)
WHERE c.collnamespace = {{scid}}::oid
{% if coid %} AND c.oid = {{coid}}::oid {% endif %}
ORDER BY c.collname;
@@ -51,7 +51,7 @@ export default class DomainConstraintSchema extends BaseUISchema {
cell:'boolean', group: gettext('Definition'), min_version: 90200,
mode: ['properties', 'create', 'edit'],
readonly: function(state) {
return !obj.isNew(state) && obj._origData.convalidated;
return !obj.isNew(state) && obj.origData.convalidated;
}
}
];
@@ -24,7 +24,7 @@ ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
{{ VARIABLE.SET(conn, 'COLUMN', data.name, data.attoptions) }}
{% endif %}
{### Alter column statistics value ###}
{% if data.attstattarget is defined and data.attstattarget > -1 %}
{% if data.attstattarget is defined and data.attstattarget is not none and data.attstattarget > -1 %}
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
ALTER COLUMN {{conn|qtTypeIdent(data.name)}} SET STATISTICS {{data.attstattarget}};
@@ -93,7 +93,7 @@ ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.basensp, data.name)}}
{% endif %}
{### Alter column statistics value ###}
{% if c.attstattarget is defined and c.attstattarget > -1 %}
{% if c.attstattarget is defined and c.attstattarget is not none and c.attstattarget > -1 %}
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.basensp, data.name)}}
ALTER COLUMN {{conn|qtTypeIdent(c.name)}} SET STATISTICS {{c.attstattarget}};
@@ -825,7 +825,7 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
if sql is None:
return None
start = 0
start_position = re.search("\\s+[is|as]+\\s+", sql, flags=re.I)
start_position = re.search("\\s+(is|as)+\\s+", sql, flags=re.I)
if start_position:
start = start_position.start() + 4
@@ -582,7 +582,7 @@ class EdbFuncView(PGChildNodeView, DataTypeReader):
if sql is None:
return None
start = 0
start_position = re.search(r"\s+[is|as]+\s+", sql, flags=re.I)
start_position = re.search(r"\s+(is|as)+\s+", sql, flags=re.I)
if start_position:
start = start_position.start() + 4
@@ -100,7 +100,10 @@ export default class PackageSchema extends BaseUISchema {
group: gettext('Header'),
depChange: (state, source, topState, actionObj) => {
if(packageSchemaObj._origData.oid && state.pkgheadsrc != actionObj.oldState.pkgheadsrc) {
if(
packageSchemaObj.origData.oid &&
state.pkgheadsrc != actionObj.oldState.pkgheadsrc
) {
packageSchemaObj.warningText = gettext(
'Updating the package header definition may remove its existing body.'
) + '<br><br><b>' + gettext('Do you want to continue?') +
@@ -116,7 +119,10 @@ export default class PackageSchema extends BaseUISchema {
mode: ['properties', 'create', 'edit'], group: gettext('Body'),
depChange: (state, source, topState, actionObj) => {
if(packageSchemaObj._origData.oid && state.pkgbodysrc != actionObj.oldState.pkgbodysrc) {
if(
packageSchemaObj.origData.oid &&
state.pkgbodysrc != actionObj.oldState.pkgbodysrc
) {
packageSchemaObj.warningText = gettext(
'Updating the package header definition may remove its existing body.'
) + '<br><br><b>' + gettext('Do you want to continue?') +
@@ -10,7 +10,7 @@
import * as Node from 'pgbrowser/node';
import * as SchemaTreeNode from './schema_child_tree_node';
let SchemaChildNode = Node.extend({
const SchemaChildNode = Node.extend({
parent_type: ['schema', 'catalog'],
canDrop: SchemaTreeNode.isTreeItemOfChildOfSchema,
canDropCascade: SchemaTreeNode.isTreeItemOfChildOfSchema,
@@ -587,7 +587,7 @@ export default class ColumnSchema extends BaseUISchema {
}
validate(state, setError) {
let msg = undefined;
let msg;
if (!_.isUndefined(state.cltype) && !isEmptyString(state.attlen)) {
// Validation for Length field
@@ -128,10 +128,7 @@ export default class CompoundTriggerSchema extends BaseUISchema {
}
// Enable column only if update event is set true
let isUpdate = state.evnt_update;
if(!_.isUndefined(isUpdate) && isUpdate) {
return false;
}
return true;
return !(!_.isUndefined(isUpdate) && isUpdate);
},
readonly: function(state) { return !obj.isNew(state); },
},{
@@ -24,6 +24,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
constraints.exclusion_constraint import utils as exclusion_utils
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import check_pgstattuple
class ExclusionConstraintModule(ConstraintTypeModule):
@@ -837,13 +839,7 @@ class ExclusionConstraintView(PGChildNodeView):
Returns the statistics for a particular object if cid is specified
"""
# Check if pgstattuple extension is already created?
# if created then only add extended stats
status, is_pgstattuple = self.conn.execute_scalar("""
SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple
FROM pg_catalog.pg_extension
WHERE extname='pgstattuple'
""")
status, is_pgstattuple = check_pgstattuple(self.conn, tid)
if not status:
return internal_server_error(errormsg=is_pgstattuple)
@@ -68,7 +68,6 @@ class ExclusionColHeaderSchema extends BaseUISchema {
return this.exColumnSchema.getNewData({
is_exp: data.is_exp,
column: data.is_exp ? data.expression : data.column,
column_cid: data.is_exp ? null : column?.cid,
col_type: data.is_exp ? null : column?.datatype,
});
}
@@ -379,13 +378,13 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
if(obj.inTable && source[0] == 'columns') {
if(actionObj.type == SCHEMA_STATE_ACTIONS.DELETE_ROW) {
let column = _.get(actionObj.oldState, actionObj.path.concat(actionObj.value));
currColumns = _.filter(currColumns, (cc)=>cc.column_cid != column.cid);
currColumns = _.filter(currColumns, (cc)=>cc.column != column.name);
} else if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE) {
let tabColPath = _.slice(actionObj.path, 0, -1);
let column = _.get(topState, tabColPath);
let idx = _.findIndex(currColumns, (cc)=>cc.column_cid == column.cid);
let tabColPath =_.slice(actionObj.path, 0, -1);
let column = _.get(actionObj.oldState, tabColPath);
let idx = _.findIndex(currColumns, (cc)=>cc.column == column.name);
if(idx > -1) {
currColumns[idx].column = column.name;
currColumns[idx].column = _.get(topState, tabColPath).name;
}
}
}
@@ -66,7 +66,6 @@ class ForeignKeyHeaderSchema extends BaseUISchema {
let references_table_name = _.find(this.refTables, (t)=>t.value==data.references || t.value == this.origData.references)?.label;
return {
local_column: data.local_column,
local_column_cid: _.find(this.fieldOptions.local_column, (c)=>c.value == data.local_column)?.cid,
referenced: data.referenced,
references: data.references,
references_table_name: references_table_name,
@@ -348,11 +347,11 @@ export default class ForeignKeySchema extends BaseUISchema {
if(obj.inTable && source[0] == 'columns') {
if(actionObj.type == SCHEMA_STATE_ACTIONS.DELETE_ROW) {
let column = _.get(actionObj.oldState, actionObj.path.concat(actionObj.value));
currColumns = _.filter(currColumns, (cc)=>cc.local_column_cid != column.cid);
currColumns = _.filter(currColumns, (cc)=>cc.local_column != column.name);
} else if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE) {
let tabColPath = _.slice(actionObj.path, 0, -1);
let column = _.get(actionObj.oldState, tabColPath);
let idx = _.findIndex(currColumns, (cc)=>cc.local_column_cid == column.cid);
let idx = _.findIndex(currColumns, (cc)=>cc.local_column == column.name);
if(idx > -1) {
currColumns[idx].local_column = _.get(topState, tabColPath).name;
}
@@ -24,6 +24,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
constraints.index_constraint import utils as idxcons_utils
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import check_pgstattuple
class IndexConstraintModule(ConstraintTypeModule):
@@ -926,13 +928,7 @@ class IndexConstraintView(PGChildNodeView):
Returns the statistics for a particular object if cid is specified
"""
# Check if pgstattuple extension is already created?
# if created then only add extended stats
status, is_pgstattuple = self.conn.execute_scalar("""
SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple
FROM pg_catalog.pg_extension
WHERE extname='pgstattuple'
""")
status, is_pgstattuple = check_pgstattuple(self.conn, tid)
if not status:
return internal_server_error(errormsg=is_pgstattuple)
@@ -86,13 +86,14 @@ export default class PrimaryKeySchema extends BaseUISchema {
if(obj.inTable && source[0] == 'columns') {
if(actionObj.type == SCHEMA_STATE_ACTIONS.DELETE_ROW) {
let oldColumn = _.get(actionObj.oldState, actionObj.path.concat(actionObj.value));
currColumns = _.filter(currColumns, (cc)=>cc.cid != oldColumn.cid);
currColumns = _.filter(currColumns, (cc)=>cc.column != oldColumn.name);
} else if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE) {
let tabColPath = _.slice(actionObj.path, 0, -1);
let oldCol = _.get(actionObj.oldState, tabColPath);
let idx = _.findIndex(currColumns, (cc)=>cc.cid == oldCol.cid);
if(idx > -1) {
currColumns[idx].column = _.get(topState, tabColPath).name;
let idx = _.findIndex(currColumns, (cc)=>cc.column == oldCol.name);
let updatedCol = _.get(topState, tabColPath);
if(idx > -1 && updatedCol.is_primary_key) {
currColumns[idx].column = updatedCol.name;
}
}
}
@@ -88,11 +88,11 @@ export default class UniqueConstraintSchema extends BaseUISchema {
if(obj.inTable && source[0] == 'columns') {
if(actionObj.type == SCHEMA_STATE_ACTIONS.DELETE_ROW) {
let oldColumn = _.get(actionObj.oldState, actionObj.path.concat(actionObj.value));
currColumns = _.filter(currColumns, (cc)=>cc.cid != oldColumn.cid);
currColumns = _.filter(currColumns, (cc)=>cc.column != oldColumn.name);
} else if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE) {
let tabColPath = _.slice(actionObj.path, 0, -1);
let oldCol = _.get(actionObj.oldState, tabColPath);
let idx = _.findIndex(currColumns, (cc)=>cc.cid == oldCol.cid);
let idx = _.findIndex(currColumns, (cc)=>cc.column == oldCol.name);
if(idx > -1) {
currColumns[idx].column = _.get(topState, tabColPath).name;
}
@@ -29,6 +29,8 @@ from pgadmin.tools.schema_diff.directory_compare import directory_diff
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
from pgadmin.browser.server_groups.servers.databases.schemas. \
tables.indexes import utils as index_utils
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import check_pgstattuple
class IndexesModule(CollectionNodeModule):
@@ -998,14 +1000,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
if idx is not None:
# Individual index
# Check if pgstattuple extension is already created?
# if created then only add extended stats
status, is_pgstattuple = self.conn.execute_scalar("""
SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple
FROM pg_catalog.pg_extension
WHERE extname='pgstattuple'
""")
status, is_pgstattuple = check_pgstattuple(self.conn, tid)
if not status:
return internal_server_error(errormsg=is_pgstattuple)
Loaded 100 of 453 files, more files were not shown because too many files have changed in this diff. Show more