Migrate pgAdmin UI to use React 19

pull/9259/head
Aditya Toshniwal 2025-10-16 14:44:27 +05:30
parent 91ad54d17b
commit 32af7cc778
204 changed files with 818 additions and 675 deletions

View File

@ -1,210 +1,299 @@
# -*- coding: utf-8 -*-
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
# Get the correct version of chromedriver for the version of Chrome on the
# machine and save it to the specified location.
import argparse
import os
import platform
import subprocess
import sys
from urllib.request import urlopen, urlretrieve
from urllib.error import URLError
import requests
import zipfile
import stat
# --- Helper Functions for Auto-Detection ---
def _find_chrome_executable():
"""Find the Chrome executable path on Linux or macOS."""
system = platform.system()
if system == 'Darwin':
# macOS standard location
paths = [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
]
elif system == 'Linux':
# Common Linux executables (Chromium and Google Chrome)
paths = [
'google-chrome',
'google-chrome-stable',
'chromium',
'chromium-browser',
]
else:
return None
for path in paths:
try:
# Check if the command/path is callable (using 'which' or
# direct check)
if system == 'Linux':
# Use 'which' for common Linux commands/paths
result = subprocess.run(
['which', path],
capture_output=True,
text=True,
check=False
)
if result.returncode == 0:
return result.stdout.strip()
# For macOS, or if 'which' failed/is unavailable, check direct path
if os.path.exists(path):
return path
except FileNotFoundError:
continue
return None
def read_command_line():
"""Read the command line arguments.
Returns:
ArgumentParser: The parsed arguments object
"""
The 'chrome' argument is now removed."""
parser = argparse.ArgumentParser(
description='Get the correct version of chromedriver for the '
'specified Chrome installation and save it.')
if platform.system() != 'Windows':
parser.add_argument("chrome", metavar="CHROME",
help="the Chrome executable")
parser.add_argument("directory", metavar="DIRECTORY",
help="the directory in which to save chromedriver")
description=(
'Auto-detects Chrome version, gets the correct Chromedriver '
'using Chrome for Testing, and saves it.'
)
)
args = parser.parse_args()
# Only accept the directory argument
parser.add_argument(
'directory',
metavar='DIRECTORY',
help='the directory in which to save chromedriver'
)
return args
return parser.parse_args()
def get_chrome_version(args):
"""Get the Chrome version number.
def get_chrome_version():
"""Get the Chrome version number via OS-specific auto-detection."""
full_version = None
Args:
args: The parsed arguments object
Returns:
The Chrome version number
"""
if platform.system() == 'Windows':
# On Windows we need to examine the resource section of the binary
import winreg
def _read_registry(root, key, value):
try:
hkey = winreg.OpenKey(root, key)
except Exception:
return None
try:
(val, typ) = winreg.QueryValueEx(hkey, value)
except Exception:
winreg.CloseKey(hkey)
return None
winreg.CloseKey(hkey)
return val
key = r'SOFTWARE\Google\Chrome\BLBeacon'
version_str = _read_registry(winreg.HKEY_CURRENT_USER, key, 'Version')
# On a 64b host, look for a 32b installation
if not version_str:
key = r'SOFTWARE\Wow6432Node\Google\Chrome\BLBeacon'
version_str = _read_registry(winreg.HKEY_CURRENT_USER, key,
'Version')
if not version_str:
print('The Chrome version could not be read from the registry.')
sys.exit(1)
chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1])
else:
# On Linux/Mac we run the Chrome executable with the --version flag,
# then parse the output.
try:
result = subprocess.Popen([args.chrome, '--version'],
stdout=subprocess.PIPE)
except FileNotFoundError:
print('The specified Chrome executable could not be found.')
import winreg
def _read_registry(root, key, value):
try:
with winreg.OpenKey(root, key) as hkey:
val, _ = winreg.QueryValueEx(hkey, value)
return val
except Exception:
return None
keys = [
r'SOFTWARE\Google\Chrome\BLBeacon',
r'SOFTWARE\Wow6432Node\Google\Chrome\BLBeacon',
]
version_str = None
for key in keys:
version_str = _read_registry(
winreg.HKEY_CURRENT_USER, key, 'Version'
)
if version_str:
break
if not version_str:
print(
'Error: The Chrome version could not be read '
'from the Windows registry.'
)
sys.exit(1)
full_version = (
version_str.split()[-1].strip()
if version_str.split()
else version_str.strip()
)
except ImportError:
print("Error: The 'winreg' module is required on Windows.")
sys.exit(1)
except Exception as e:
print(f"Error reading Windows registry: {e}")
sys.exit(1)
version_str = result.stdout.read().decode("utf-8")
# Check for 'Chrom' not 'Chrome' in case the user is using Chromium.
if "Chrom" not in version_str:
print('The specified Chrome executable output an unexpected '
'version string: {}.'.format(version_str))
else:
chrome_executable = _find_chrome_executable()
if not chrome_executable:
print(
'Error: Could not find the Google Chrome or Chromium '
'executable in common locations.'
)
sys.exit(1)
# On some linux distro `chrome--version` gives output like
# 'Google Chrome 80.0.3987.132 unknown\n'
# so we need to check and remove the unknown string from the version
if version_str.endswith("unknown\n"):
version_str = version_str.strip("unknown\n").strip()
chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1])
try:
result = subprocess.run(
[chrome_executable, '--version'],
capture_output=True,
text=True,
check=True
)
if chrome_version.count('.') != 2:
print('The specified Chrome executable output an unexpected '
'version string: {}.'.format(version_str))
version_str = result.stdout.strip()
if 'Chrom' not in version_str:
print(
'Error: Executable output unexpected version string: '
f'{version_str}'
)
sys.exit(1)
full_version = version_str.split()[-1]
except subprocess.CalledProcessError as e:
print(f"Error executing '{chrome_executable} --version': {e}")
sys.exit(1)
if not full_version or full_version.count('.') < 3:
print(f'Error: Extracted Chrome version "{full_version}" '
f'seems invalid.')
sys.exit(1)
return chrome_version
return full_version
def get_chromedriver_version(chrome_version):
"""Get the required chromedriver version number.
def get_system_and_platform():
"""Get the CfT platform name (e.g., mac-arm64, linux64)."""
system = platform.system()
Args:
chrome_version: The chrome version number
Returns:
The chromedriver version number
"""
url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_{}' \
.format(chrome_version)
if system == 'Darwin':
if platform.machine() in ('arm64', 'aarch64'):
return 'mac-arm64'
return 'mac-x64'
if system == 'Linux':
return 'linux64'
if system == 'Windows':
return 'win64'
print(f'Error: Unknown or unsupported operating system: {system}')
sys.exit(1)
def get_chromedriver_download_url(full_chrome_version, cft_platform):
"""Get the required Chromedriver version and download URL using CfT."""
download_url = (
'https://storage.googleapis.com/chrome-for-testing-public/'
f'{full_chrome_version}/{cft_platform}/'
f'chromedriver-{cft_platform}.zip'
)
return full_chrome_version, download_url
def download_and_extract(url, target_directory, cft_platform):
"""Downloads the zip, extracts chromedriver, and sets permissions."""
print(f'Downloading from: {url}')
temp_zip_path = os.path.join(target_directory, 'chromedriver_temp.zip')
try:
response = requests.get(url, stream=True)
response.raise_for_status()
with open(temp_zip_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
except Exception as e:
print(f'Error during download: {e}')
sys.exit(1)
print('Extracting chromedriver...')
chromedriver_in_zip_dir = f'chromedriver-{cft_platform}/'
if cft_platform.startswith('win'):
chromedriver_in_zip = chromedriver_in_zip_dir + 'chromedriver.exe'
chromedriver_target_name = 'chromedriver.exe'
else:
chromedriver_in_zip = chromedriver_in_zip_dir + 'chromedriver'
chromedriver_target_name = 'chromedriver'
target_path = os.path.join(target_directory, chromedriver_target_name)
found = False
try:
fp = urlopen(url)
except URLError as e:
print('The chromedriver catalog URL could not be accessed: {}'
.format(e))
with zipfile.ZipFile(temp_zip_path, 'r') as z:
for name in z.namelist():
if name == chromedriver_in_zip:
with z.open(name) as source, open(
target_path, 'wb'
) as target:
target.write(source.read())
found = True
break
except Exception as e:
print(f'Error during extraction: {e}')
sys.exit(1)
finally:
os.remove(temp_zip_path)
if not found:
print(f"Error: '{chromedriver_in_zip}' not found in archive.")
sys.exit(1)
version = fp.read().decode("utf-8").strip()
fp.close()
if not cft_platform.startswith('win'):
print('Setting executable permissions.')
os.chmod(
target_path,
stat.S_IRWXU |
stat.S_IRGRP |
stat.S_IXGRP |
stat.S_IROTH |
stat.S_IXOTH
)
return version
print(f'\nSuccess! Chromedriver downloaded and saved to: {target_path}')
def get_system():
"""Get the system name as known to chromedriver
# --- Core Logic ---
Returns:
The system name
"""
if platform.system() == 'Darwin':
return 'mac64'
elif platform.system() == 'Linux':
return 'linux64'
elif platform.system() == 'Windows':
return 'win32'
else:
print("Unknown or unsupported operating system: {}"
.format(platform.system()))
def main():
"""The core structure of the app."""
try:
import requests # noqa: F401
except ImportError:
print(
"Error: The 'requests' library is required. "
"Please install it with 'pip install requests'"
)
sys.exit(1)
args = read_command_line()
"""The core structure of the app."""
if not os.path.isdir(args.directory):
print(
f'Error: The specified output directory "{args.directory}" '
'could not be accessed.'
)
sys.exit(1)
# Read the command line options
args = read_command_line()
cft_platform = get_system_and_platform()
current_system = platform.system()
print(f'Detected OS: {current_system} | '
f'Target CfT Platform: {cft_platform}')
chrome_version = get_chrome_version(args)
full_chrome_version = get_chrome_version()
print(f'Detected Chrome Version: {full_chrome_version}')
# Check the directory exists
if not os.path.isdir(args.directory):
print('The specified output directory could not be accessed.')
sys.exit(1)
chromedriver_version, download_url = get_chromedriver_download_url(
full_chrome_version, cft_platform
)
print(f'Downloading chromedriver v{chromedriver_version}...')
chromedriver_version = get_chromedriver_version(chrome_version)
download_and_extract(download_url, args.directory, cft_platform)
system = get_system()
url = 'https://chromedriver.storage.googleapis.com/{}/chromedriver_{}.zip' \
.format(chromedriver_version, system)
print('Downloading chromedriver v{} for Chrome v{} on {}...'
.format(chromedriver_version, chrome_version, system))
try:
file, headers = urlretrieve(url)
except URLError as e:
print('The chromedriver download URL could not be accessed: {}'
.format(e))
sys.exit(1)
# Unzip chromedriver
print('Extracting chromedriver...')
found = False
fp = open(file, 'rb')
z = zipfile.ZipFile(fp)
for name in z.namelist():
if (system == 'win32' and name == 'chromedriver.exe') or \
(system != 'win32' and name == 'chromedriver'):
z.extract(name, args.directory)
found = True
fp.close()
if not found:
print("chromedriver could not be found in the downloaded archive: {}"
.format(file))
sys.exit(1)
# Set the permissions
if system == 'mac64' or system == 'linux64':
os.chmod(os.path.join(args.directory, 'chromedriver'), 0o755)
print('Chromedriver downloaded to: {}'.format(args.directory))
if __name__ == '__main__':
main()

View File

@ -92,7 +92,9 @@ module.exports = [
'no-import-assign': 'off',
...reactjs.configs.recommended.rules,
...reactjs.configs['jsx-runtime'].rules,
'react/jsx-uses-react': 'error',
'react/prop-types': 'off',
'react/react-in-jsx-scope': 0,
'react/jsx-uses-react': 0,
'react/jsx-uses-vars': 'error',
'no-unused-vars': 'off',
'unused-imports/no-unused-imports': 'error',

View File

@ -1,4 +1,6 @@
{
"presets": [["@babel/preset-env", {"modules": "commonjs", "useBuiltIns": "usage", "corejs": 3}], "@babel/preset-react", "@babel/preset-typescript"],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/proposal-object-rest-spread", "@babel/plugin-transform-runtime"]
"presets": [["@babel/preset-env", {"modules": "commonjs", "useBuiltIns": "usage", "corejs": 3}], ["@babel/preset-react", {
"runtime": "automatic"
}], "@babel/preset-typescript"],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/proposal-object-rest-spread"]
}

View File

@ -2,7 +2,8 @@ const webpackShimAlias = require('./webpack.shim').resolveAlias;
const webpackAliasToJestModules = ()=>{
const ret = {
'\\.svg': '<rootDir>/regression/javascript/__mocks__/svg.js'
'\\.svg\\?svgr$': '<rootDir>/regression/javascript/__mocks__/svg.js',
'react-dom/server': 'react-dom/server.edge',
};
Object.keys(webpackShimAlias).forEach((an)=>{
// eg - sources: ./pgadmin/static/js/ to '^sources/(.*)$': '<rootDir>/pgadmin/static/js/$1'

View File

@ -71,7 +71,7 @@
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-react": "^7.12.13",
"@babel/preset-react": "^7.27.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.10.0",
"@date-io/core": "^3.0.0",
@ -90,8 +90,8 @@
"@tanstack/react-table": "^8.16.0",
"@tanstack/react-virtual": "^3.13.6",
"@types/classnames": "^2.3.4",
"@types/react": "^18.0.2",
"@types/react-dom": "^18.0.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-search": "^0.15.0",
"@xterm/addon-web-links": "^0.11.0",
@ -124,15 +124,15 @@
"papaparse": "^5.5.2",
"path-fx": "^2.0.0",
"postcss": "^8.5.6",
"rc-dock": "^3.3.2",
"react": "^18.2.0",
"rc-dock": "^4.0.0-alpha.2",
"react": "^19.0.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#3dfc2ca01a046d55c1c7a45392dcec104815dc76",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-dom": "^19.0.0",
"react-draggable": "^4.4.6",
"react-dropzone": "^14.2.1",
"react-frame-component": "^5.2.6",

View File

@ -9,7 +9,7 @@
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';
import React, { useEffect, useState, useRef } from 'react';
import { useEffect, useState, useRef } from 'react';
import { Box, Grid, InputLabel } from '@mui/material';
import { InputSQL } from '../../../static/js/components/FormComponents';
import getApiInstance from '../../../static/js/api_instance';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import gettext from 'sources/gettext';
import pgAdmin from 'sources/pgadmin';
import AboutComponent from './AboutComponent';

View File

@ -10,7 +10,6 @@
import _ from 'lodash';
import getApiInstance from '../../../static/js/api_instance';
import { AllPermissionTypes, BROWSER_PANELS } from './constants';
import React from 'react';
import ObjectNodeProperties from '../../../misc/properties/ObjectNodeProperties';
import ErrorBoundary from '../../../static/js/helpers/ErrorBoundary';
import toPx from '../../../static/js/to_px';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo, useState, Fragment } from 'react';
import { useEffect, useMemo, useState, Fragment } from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useRef, useState, useReducer, useMemo } from 'react';
import { useEffect, useRef, useState, useReducer, useMemo } from 'react';
import { DATA_POINT_SIZE } from 'sources/chartjs';
import ChartContainer from './components/ChartContainer';
import url_for from 'sources/url_for';

View File

@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
export default function PgAdminLogo() {

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box } from '@mui/material';
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import gettext from 'sources/gettext';
import ReplicationSlotsSchema from './schema_ui/replication_slots.ui';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box, Grid, useTheme } from '@mui/material';
import React, { useEffect, useMemo, useReducer, useRef, useState } from 'react';
import { useEffect, useMemo, useReducer, useRef, useState } from 'react';
import gettext from 'sources/gettext';
import PgTable from 'sources/components/PgTable';

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////
import React from 'react';
import PropTypes from 'prop-types';
import LogReplication from './LogReplication';
import EmptyPanelMessage from '../../../../static/js/components/EmptyPanelMessage';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import PgTable from 'sources/components/PgTable';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import PgTable from 'sources/components/PgTable';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { useState, useEffect, useRef, useReducer, useMemo } from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import _ from 'lodash';

View File

@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import PropTypes from 'prop-types';
import { Box, Card, CardContent, CardHeader } from '@mui/material';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined';

View File

@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import PropTypes from 'prop-types';
import { Box } from '@mui/material';

View File

@ -1,6 +1,5 @@
import { Box } from '@mui/material';
import { styled } from '@mui/material/styles';
import React from 'react';
import CloseIcon from '@mui/icons-material/CloseRounded';
import { DefaultButton, PgIconButton } from '../../../../static/js/components/Buttons';
import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useMemo } from 'react';
import { useState, useMemo } from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';

View File

@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
import CloudWizard from './CloudWizard';
import getApiInstance from '../../../../static/js/api_instance';
import { BROWSER_PANELS } from '../../../../browser/static/js/constants';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { ToggleButton, ToggleButtonGroup, TableBody, TableCell, TableHead, TableRow } from '@mui/material';
import CheckRoundedIcon from '@mui/icons-material/CheckRounded';
import { DefaultButton, PrimaryButton } from '../../../../static/js/components/Buttons';

View File

@ -8,7 +8,6 @@
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext';
import React from 'react';
import FileManager from './components/FileManager';
import { getBrowser } from '../../../../static/js/utils';
import pgAdmin from 'sources/pgadmin';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box } from '@mui/material';
import { styled } from '@mui/material/styles';
import React, {useState, useEffect, useRef, useLayoutEffect} from 'react';
import {useState, useEffect, useRef, useLayoutEffect} from 'react';
import FolderIcon from '@mui/icons-material/Folder';
import DescriptionIcon from '@mui/icons-material/Description';
import LockRoundedIcon from '@mui/icons-material/LockRounded';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useCallback, useReducer, useEffect, useMemo } from 'react';
import { useCallback, useReducer, useEffect, useMemo } from 'react';
import { styled } from '@mui/material/styles';
import { Box, List, ListItem } from '@mui/material';
import CloseIcon from '@mui/icons-material/CloseRounded';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import CollectionNodeProperties from './CollectionNodeProperties';
import ErrorBoundary from '../../static/js/helpers/ErrorBoundary';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';
import _ from 'lodash';
@ -229,7 +229,6 @@ class AdHocConnectionSchema extends BaseUISchema {
return {type: 'text'};
}
},
optionsLoaded: (res) => this.dbs = res,
depChange: (state) => {
/* Once the option is selected get the name */
return {

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { usePgAdmin } from '../../../../static/js/PgAdminProvider';
import { Box } from '@mui/material';
import { QueryToolIcon, SchemaDiffIcon } from '../../../../static/js/components/ExternalIcon';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';

View File

@ -10,7 +10,6 @@
import gettext from 'sources/gettext';
import { BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/constants';
import WorkspaceWelcomePage from './WorkspaceWelcomePage';
import React from 'react';
import { LayoutDocker } from '../../../../static/js/helpers/Layout';
const welcomeQueryToolPanelData = [{

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Resizable } from 're-resizable';
// Import helpers from new file

View File

@ -11,7 +11,6 @@ import gettext from 'sources/gettext';
import { styled } from '@mui/material/styles';
import _ from 'lodash';
import url_for from 'sources/url_for';
import React from 'react';
import { Box } from '@mui/material';
import { DefaultButton, PrimaryButton } from '../../../../static/js/components/Buttons';
import { getBinaryPathSchema } from './binary_path.ui';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext';
import React, { useEffect, useRef, useCallback } from 'react';
import { useEffect, useRef, useCallback } from 'react';
import { Box, Link } from '@mui/material';
import PropTypes from 'prop-types';
import SchemaView from '../../../../static/js/SchemaView';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import ReactDOM from 'react-dom/client';
import BrowserComponent from '../js/BrowserComponent';
import MainMenuFactory from '../../browser/static/js/MainMenuFactory';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box } from '@mui/material';
import { styled } from '@mui/material/styles';
import React, { useEffect } from 'react';
import { useEffect } from 'react';
import { PrimaryButton } from './components/Buttons';
import { PgMenu, PgMenuDivider, PgMenuItem, PgSubMenu } from './components/Menu';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, {useEffect, useMemo, useState } from 'react';
import {useEffect, useMemo, useState } from 'react';
import AppMenuBar from './AppMenuBar';
import ObjectBreadcrumbs from './components/ObjectBreadcrumbs';
import Layout, { LAYOUT_EVENTS, LayoutDocker, getDefaultGroup } from './helpers/Layout';

View File

@ -1,4 +1,3 @@
import React from 'react';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';
import BaseUISchema from '../SchemaView/base_schema.ui';

View File

@ -1,4 +1,3 @@
import React from 'react';
import { ModalContent, ModalFooter } from '../../../static/js/components/ModalContent';
import gettext from 'sources/gettext';
import { Box } from '@mui/material';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useRef, useEffect, useLayoutEffect } from 'react';
import { useState, useRef, useEffect, useLayoutEffect } from 'react';
import gettext from 'sources/gettext';
import { Box } from '@mui/material';
import { DefaultButton, PrimaryButton } from '../components/Buttons';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useRef, useEffect } from 'react';
import { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useRef, useEffect } from 'react';
import { useState, useRef, useEffect } from 'react';
import gettext from 'sources/gettext';
import { Box } from '@mui/material';
import { DefaultButton, PrimaryButton } from '../components/Buttons';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import _ from 'lodash';
import React, { useState, useRef, useMemo } from 'react';
import { useState, useRef, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Box } from '@mui/material';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import pgAdmin from 'sources/pgadmin';
import ConnectServerContent from './ConnectServerContent';
import url_for from 'sources/url_for';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import PropTypes from 'prop-types';
// Allow us to render IFrame using React

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, {useRef,useState, useEffect} from 'react';
import {useRef,useState, useEffect} from 'react';
import { styled } from '@mui/material/styles';
import { CircularProgress, Typography } from '@mui/material';
import {useDelayDebounce} from 'sources/custom_hooks';

View File

@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
import ReactDOM from 'react-dom/client';
import HiddenIframe from './HiddenIframe';
import url_for from 'sources/url_for';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext } from 'react';
import { useContext } from 'react';
import {
SEARCH_INPUT_ALIGNMENT, SEARCH_INPUT_SIZE, SearchInputText,

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
export const ACTION_COLUMN = {
header: <>&nbsp;</>,

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useRef } from 'react';
import { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import DragIndicatorRoundedIcon from '@mui/icons-material/DragIndicatorRounded';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, {
import {
useCallback, useContext, useEffect, useRef, useState
} from 'react';
import { styled } from '@mui/material/styles';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, {
import {
useContext, useEffect, useMemo, useRef, useState,
} from 'react';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useCallback, useContext, useEffect, useRef } from 'react';
import { useCallback, useContext, useEffect, useRef } from 'react';
import Box from '@mui/material/Box';
import AddIcon from '@mui/icons-material/AddOutlined';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext, useMemo, useState } from 'react';
import { useContext, useMemo, useState } from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,8 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext, useMemo, useRef } from 'react';
import { useContext, useMemo, useRef } from 'react';
import Draggable from 'react-draggable';
import { flexRender } from '@tanstack/react-table';
@ -54,31 +55,33 @@ export function DataGridRow({row, isResizing}) {
return useMemo(() => (
!row ? <></> :
<DataGridRowContext.Provider value={{ rowAccessPath, row }}>
<PgReactTableRowContent ref={rowRef}
className={classList.join[' ']}
data-test='data-table-row' style={{position: 'initial'}}
{...attributes}
>
{
row?.getVisibleCells().map((cell) => {
const columnDef = cell.column.columnDef;
const content = flexRender(
columnDef.cell, {
key: columnDef.cell?.type ?? columnDef.id,
row: row,
getValue: cell.getValue,
}
);
<Draggable nodeRef={rowRef}>
<PgReactTableRowContent ref={rowRef}
className={classList.join[' ']}
data-test='data-table-row' style={{position: 'initial'}}
{...attributes}
>
{
row?.getVisibleCells().map((cell) => {
const columnDef = cell.column.columnDef;
const content = flexRender(
columnDef.cell, {
key: columnDef.cell?.type ?? columnDef.id,
row: row,
getValue: cell.getValue,
}
);
return (
<PgReactTableCell cell={cell} row={row} key={cell.id}>
{content}
</PgReactTableCell>
);
})
}
<div className='hover-overlay'></div>
</PgReactTableRowContent>
return (
<PgReactTableCell cell={cell} row={row} key={cell.id}>
{content}
</PgReactTableCell>
);
})
}
<div className='hover-overlay'></div>
</PgReactTableRowContent>
</Draggable>
{
expandedRowContents.length ?
<PgReactTableRowExpandContent

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { isModeSupportedByField } from 'sources/SchemaView/common';
import { getMappedCell } from '../mappedCell';

View File

@ -7,15 +7,15 @@
//
//////////////////////////////////////////////////////////////
import React, { useMemo } from 'react';
import { useMemo } from 'react';
export const FieldControl = ({schemaId, item}) => {
const Control = item.control;
const props = item.controlProps;
const {key, ...props} = item.controlProps;
const children = item.controls;
return useMemo(() =>
<Control {...props}>
<Control key={key} {...props}>
{
children?.map(
(child, idx) => <FieldControl key={`${child.controlProps.id}-${idx}`} item={child}/>

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext, useEffect, useState, useMemo } from 'react';
import { useContext, useEffect, useState, useMemo } from 'react';
import Loader from 'sources/components/Loader';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Tab } from '@mui/material';
import React, { useContext, useState } from 'react';
import { useContext, useState } from 'react';
import { useFieldOptions, useSchemaStateSubscriber } from './hooks';
import { SchemaStateContext } from './SchemaState';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext } from 'react';
import { useContext } from 'react';
import { Grid } from '@mui/material';
import _ from 'lodash';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useCallback, useContext, useMemo, useState } from 'react';
import { useCallback, useContext, useMemo, useState } from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext, useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import { DefaultButton } from 'sources/components/Buttons';
import { SchemaStateContext } from './SchemaState';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { InputSQL } from 'sources/components/FormComponents';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useContext, useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import { PrimaryButton } from 'sources/components/Buttons';
import { SchemaStateContext } from './SchemaState';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useState, useEffect, useMemo } from 'react';
import { useState, useEffect, useMemo } from 'react';
import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import InfoIcon from '@mui/icons-material/InfoRounded';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import PropTypes from 'prop-types';

View File

@ -1,7 +1,7 @@
import { Box, Button, darken } from '@mui/material';
import { styled } from '@mui/material/styles';
import { useSnackbar } from 'notistack';
import React, { useEffect } from 'react';
import { useEffect } from 'react';
import { MESSAGE_TYPE, NotifierMessage } from '../components/FormComponents';
import { FinalNotifyContent } from '../helpers/Notifier';
import PropTypes from 'prop-types';

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import { useState } from 'react';
import ForgotPasswordImage from '../../img/forgot_password.svg?svgr';
import { InputText } from '../components/FormComponents';
import BasePage, { SecurityButton } from './BasePage';

View File

@ -1,5 +1,5 @@
import { Box, Icon } from '@mui/material';
import React, { useState } from 'react';
import { useState } from 'react';
import LoginImage from '../../img/login.svg?svgr';
import { InputSelectNonSearch, InputText, MESSAGE_TYPE, NotifierMessage } from '../components/FormComponents';
import BasePage, { SecurityButton } from './BasePage';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import { Box } from '@mui/material';
import React, { useState } from 'react';
import { useState } from 'react';
import LoginImage from '../../img/login.svg?svgr';
import { FormNote, InputText } from '../components/FormComponents';
import BasePage, { SecurityButton } from './BasePage';

View File

@ -6,7 +6,7 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useState } from 'react';
import { useState } from 'react';
import LoginImage from '../../img/login.svg?svgr';
import { InputSelect, InputText, MESSAGE_TYPE, NotifierMessage } from '../components/FormComponents';
import BasePage, { SecurityButton } from './BasePage';

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import { useState } from 'react';
import ForgotPasswordImage from '../../img/forgot_password.svg?svgr';
import { InputText } from '../components/FormComponents';
import BasePage, { SecurityButton } from './BasePage';

View File

@ -1,5 +1,4 @@
import ReactDOM from 'react-dom/client';
import React from 'react';
import { SnackbarProvider } from 'notistack';
import Theme from '../Theme/index';
import LoginPage from './LoginPage';

View File

@ -12,7 +12,7 @@
* custom themes info will come here.
*/
import React, { useEffect, useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';

View File

@ -1,5 +1,4 @@
import PropTypes from 'prop-types';
import React from 'react';
import gettext from 'sources/gettext';
import { LAYOUT_EVENTS } from './helpers/Layout';
import { styled } from '@mui/material/styles';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useLayoutEffect, useRef } from 'react';
import { useEffect, useLayoutEffect, useRef } from 'react';
import ReactDOM from 'react-dom/client';
import { usePgAdmin } from './PgAdminProvider';
import { BROWSER_PANELS } from '../../browser/static/js/constants';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useRef } from 'react';
import { useEffect, useRef } from 'react';
import getApiInstance from 'sources/api_instance';
import {getHelpUrl, getEPASHelpUrl} from 'pgadmin.help';
import SchemaView from 'sources/SchemaView';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Button, ButtonGroup, Tooltip } from '@mui/material';
import React, { forwardRef, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import CustomPropTypes from '../custom_prop_types';
import ShortcutTitle from './ShortcutTitle';
@ -125,7 +125,7 @@ const StyledButton = styled(Button)(({theme, color}) => ({
/* pgAdmin primary button */
export const PrimaryButton = forwardRef((props, ref)=>{
export function PrimaryButton({ref, ...props}) {
let {children, className, size, noBorder, ...otherProps} = props;
let allClassName = ['Buttons-primaryButton', className];
if(size == 'xs') {
@ -137,7 +137,7 @@ export const PrimaryButton = forwardRef((props, ref)=>{
return (
<StyledButton ref={ref} size={size} className={allClassName.join(' ')} data-label={dataLabel} {...otherProps} color="primary" variant="contained">{children}</StyledButton>
);
});
};
PrimaryButton.displayName = 'PrimaryButton';
PrimaryButton.propTypes = {
size: PropTypes.string,
@ -147,7 +147,7 @@ PrimaryButton.propTypes = {
};
/* pgAdmin default button */
export const DefaultButton = forwardRef((props, ref)=>{
export function DefaultButton({ref, ...props}) {
let {children, className, size, noBorder, color, ...otherProps} = props;
let variant = 'outlined';
let allClassName = ['Buttons-defaultButton', className];
@ -162,7 +162,7 @@ export const DefaultButton = forwardRef((props, ref)=>{
return (
<StyledButton variant={variant} ref={ref} size={size} className={allClassName.join(' ')} data-label={dataLabel} {...otherProps} color={color ?? 'default'} >{children}</StyledButton>
);
});
};
DefaultButton.displayName = 'DefaultButton';
DefaultButton.propTypes = {
size: PropTypes.string,
@ -174,7 +174,7 @@ DefaultButton.propTypes = {
/* pgAdmin Icon button, takes Icon component as input */
export const PgIconButton = forwardRef(({icon, title, shortcut, className, splitButton, style, color, isDropdown, tooltipPlacement, ...props}, ref)=>{
export function PgIconButton({ref, icon, title, shortcut, className, splitButton, style, color, isDropdown, tooltipPlacement, ...props}) {
const [tooltipOpen, setTooltipOpen] = useState(false);
let shortcutTitle = null;
if(shortcut) {
@ -245,7 +245,7 @@ export const PgIconButton = forwardRef(({icon, title, shortcut, className, split
</Tooltip>
);
}
});
};
PgIconButton.displayName = 'PgIconButton';
PgIconButton.propTypes = {
icon: CustomPropTypes.children,
@ -261,14 +261,14 @@ PgIconButton.propTypes = {
tooltipPlacement: PropTypes.string,
};
export const PgButtonGroup = forwardRef(({children, ...props}, ref)=>{
export function PgButtonGroup({ref, children, ...props}) {
/* Tooltip does not work for disabled items */
return (
<ButtonGroup ref={ref} {...props}>
{children}
</ButtonGroup>
);
});
};
PgButtonGroup.displayName = 'PgButtonGroup';
PgButtonGroup.propTypes = {
children: CustomPropTypes.children,

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { PgMenu, PgMenuDivider, PgMenuItem, PgSubMenu } from './Menu';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import { styled } from '@mui/material/styles';
import { Box } from '@mui/material';
import InfoRoundedIcon from '@mui/icons-material/InfoRounded';

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React from 'react';
import QueryToolSvg from '../../img/fonticon/query_tool.svg?svgr';
import ViewDataSvg from '../../img/fonticon/view_data.svg?svgr';
import SaveDataSvg from '../../img/fonticon/save_data_changes.svg?svgr';

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////
import { styled } from '@mui/material/styles';
import React from 'react';
import PropTypes from 'prop-types';
import CustomPropTypes from '../custom_prop_types';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
/* Common form components used in pgAdmin */
import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { styled } from '@mui/material/styles';
import {
Box, FormControl, OutlinedInput, FormHelperText, ToggleButton, ToggleButtonGroup,
@ -354,8 +354,7 @@ FormInputDateTimePicker.propTypes = {
};
/* Use forwardRef to pass ref prop to OutlinedInput */
export const InputText = forwardRef(({
cid, helpid, readonly, disabled, value, onChange, controlProps, type, size, inputStyle, ...props }, ref) => {
export function InputText({ref, cid, helpid, readonly, disabled, value, onChange, controlProps, type, size, inputStyle, ...props }) {
const maxlength = typeof(controlProps?.maxLength) != 'undefined' ? controlProps.maxLength : 255;
const patterns = {
@ -427,7 +426,7 @@ export const InputText = forwardRef(({
{...(['numeric', 'int'].indexOf(type) > -1 ? { type: 'tel' } : { type: type })}
/>
);
});
};
InputText.displayName = 'InputText';
InputText.propTypes = {
cid: PropTypes.string,
@ -657,14 +656,14 @@ InputRadio.propTypes = {
labelPlacement: PropTypes.string
};
export const ToggleCheckButton = forwardRef(({ value, selected, label, ...props }, ref) => {
export function ToggleCheckButton({ref, value, selected, label, ...props}) {
return (
<ToggleButton ref={ref} value={value} component={selected ? PrimaryButton : DefaultButton}
aria-label={label} {...props}>
<CheckRoundedIcon style={{ visibility: selected ? 'visible' : 'hidden', fontSize: '1.2rem' }} />&nbsp;{label}
</ToggleButton>
);
});
};
ToggleCheckButton.displayName = 'ToggleCheckButton';
ToggleCheckButton.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
@ -673,7 +672,7 @@ ToggleCheckButton.propTypes = {
label: PropTypes.string,
};
export const InputToggle = forwardRef(({ cid, value, onChange, options, disabled, readonly, helpid, ...props }, ref) => {
export function InputToggle({ ref, cid, value, onChange, options, disabled, readonly, helpid, ...props }) {
return (
<>
<ToggleButtonGroup
@ -696,7 +695,7 @@ export const InputToggle = forwardRef(({ cid, value, onChange, options, disabled
{helpid && <input style={{display: 'none'}} defaultValue={options?.find((o)=>o.value==value)?.label} id={cid} aria-describedby={helpid} />}
</>
);
});
};
InputToggle.displayName = 'InputToggle';
InputToggle.propTypes = {
cid: PropTypes.string,
@ -917,8 +916,7 @@ InputSelectNonSearch.propTypes = {
})),
};
export const InputSelect = forwardRef(({
cid, helpid, onChange, options, readonly = false, value, controlProps = {}, optionsLoaded, optionsReloadBasis, disabled, onError, ...props }, ref) => {
export function InputSelect({ref, cid, helpid, onChange, options, readonly = false, value, controlProps = {}, optionsLoaded, optionsReloadBasis, disabled, onError, ...props}) {
const [[finalOptions, isLoading], setFinalOptions] = useState([[], true]);
const theme = useTheme();
@ -1012,7 +1010,7 @@ export const InputSelect = forwardRef(({
value: realValue,
menuPortalTarget: document.body,
styles: styles,
inputId: cid,
inputId: `${cid}-autocomplete`,
placeholder: (readonly || disabled) ? '' : controlProps.placeholder || gettext('Select an item...'),
maxLength: controlProps.maxLength,
...otherProps,
@ -1045,7 +1043,7 @@ export const InputSelect = forwardRef(({
</>
);
}
});
};
InputSelect.displayName = 'InputSelect';
InputSelect.propTypes = {
cid: PropTypes.string,

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo, useRef } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { createJSONEditor } from 'vanilla-jsoneditor';
import PropTypes from 'prop-types';
import CustomPropTypes from '../custom_prop_types';

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box, ToggleButtonGroup } from '@mui/material';
import React, { useMemo } from 'react';
import { useMemo } from 'react';
import { InputText, ToggleCheckButton } from './FormComponents';
import PropTypes from 'prop-types';
import { isMac } from '../keyboard_shortcuts';

View File

@ -9,7 +9,6 @@
import { CircularProgress, Box, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
import React from 'react';
import PropTypes from 'prop-types';
const StyledBox = styled(Box)(({theme}) => ({

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import React, { forwardRef } from 'react';
import { styled } from '@mui/material/styles';
import CustomPropTypes from '../custom_prop_types';
import { Box } from '@mui/material';
@ -29,11 +28,17 @@ const StyledBox = styled(Box)(({theme})=>({
},
}));
export const ModalContent = forwardRef(({children, ...props }, ref) => {
export function ModalContent(
{
ref,
children,
...props
}
) {
return (
<StyledBox style={{height: '100%'}} ref={ref} {...props}>{children}</StyledBox>
);
});
};
ModalContent.displayName = 'ModalContent';
ModalContent.propTypes = {
children: CustomPropTypes.children,

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box } from '@mui/material';
import { styled } from '@mui/material/styles';
import React, { useState, useEffect } from 'react';
import { useState, useEffect } from 'react';
import AccountTreeIcon from '@mui/icons-material/AccountTree';
import CommentIcon from '@mui/icons-material/Comment';
import ArrowForwardIosRoundedIcon from '@mui/icons-material/ArrowForwardIosRounded';

View File

@ -1,4 +1,4 @@
import React, { useRef, useMemo } from 'react';
import { useRef, useMemo } from 'react';
import UplotReact from 'uplot-react';
import { useResizeDetector } from 'react-resize-detector';
import gettext from 'sources/gettext';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { forwardRef, useEffect } from 'react';
import React, { useEffect } from 'react';
import { flexRender } from '@tanstack/react-table';
import { styled } from '@mui/material/styles';
import PropTypes from 'prop-types';
@ -161,7 +161,15 @@ const StyledDiv = styled('div')(({theme})=>({
}
}));
export const PgReactTableCell = forwardRef(({row, cell, children, className}, ref)=>{
export function PgReactTableCell(
{
ref,
row,
cell,
children,
className
}
) {
let classNames = ['pgrd-row-cell'];
if (typeof (cell.column.id) == 'string' && cell.column.id.startsWith('btn-')) {
classNames.push('btn-cell');
@ -195,7 +203,7 @@ export const PgReactTableCell = forwardRef(({row, cell, children, className}, re
<div className='pgrd-row-cell-content'>{children}</div>
</div>
);
});
};
PgReactTableCell.displayName = 'PgReactTableCell';
PgReactTableCell.propTypes = {
@ -205,26 +213,40 @@ PgReactTableCell.propTypes = {
className: PropTypes.any,
};
export const PgReactTableRow = forwardRef(({ children, className, ...props }, ref)=>{
export function PgReactTableRow (
{
ref,
children,
className,
...props
}
) {
return (
<div className={['pgrt-row', className].join(' ')} ref={ref} {...props}>
{children}
</div>
);
});
};
PgReactTableRow.displayName = 'PgReactTableRow';
PgReactTableRow.propTypes = {
children: CustomPropTypes.children,
className: PropTypes.any,
};
export const PgReactTableRowContent = forwardRef(({children, className, ...props}, ref)=>{
export function PgReactTableRowContent(
{
ref,
children,
className,
...props
}
) {
return (
<div className={['pgrt-row-content', className].join(' ')} ref={ref} {...props}>
{children}
</div>
);
});
};
PgReactTableRowContent.displayName = 'PgReactTableRowContent';
PgReactTableRowContent.propTypes = {
children: CustomPropTypes.children,
@ -306,7 +328,17 @@ PgReactTableBody.propTypes = {
children: CustomPropTypes.children,
};
export const PgReactTable = forwardRef(({children, table, rootClassName, tableClassName, onScrollFunc, ...props}, ref)=>{
export function PgReactTable(
{
ref,
children,
table,
rootClassName,
tableClassName,
onScrollFunc,
...props
}
) {
const columns = table.getAllColumns();
useEffect(()=>{
@ -339,7 +371,7 @@ export const PgReactTable = forwardRef(({children, table, rootClassName, tableCl
</div>
</StyledDiv>
);
});
};
PgReactTable.displayName = 'PgReactTable';
PgReactTable.propTypes = {
table: PropTypes.object,

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////
import { useSingleAndDoubleClick } from '../../../custom_hooks';
import * as React from 'react';
import PropTypes from 'prop-types';
import CustomPropTypes from '../../../../js/custom_prop_types';
import { getEnterKeyHandler } from '../../../../js/utils';

View File

@ -32,7 +32,7 @@ export class FileTreeX extends React.Component<IFileTreeXProps> {
private readonly pseudoActiveFileDec: Decoration;
private activeFile: FileOrDir;
private pseudoActiveFile: FileOrDir;
private readonly wrapperRef: React.RefObject<HTMLDivElement> = React.createRef();
private readonly wrapperRef: React.RefObject<HTMLDivElement | null> = React.createRef();
private readonly events: Notificar<FileTreeXEvent>;
private readonly disposables: DisposablesComposite;
private keyboardHotkeys: KeyboardHotkeys;

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////
import { styled } from '@mui/material/styles';
import _ from 'lodash';
import React from 'react';
import { InputCheckbox, InputText } from './FormComponents';
import PropTypes from 'prop-types';

View File

@ -10,7 +10,6 @@
import gettext from 'sources/gettext';
import _ from 'lodash';
import { FormGroup, Grid, Typography } from '@mui/material';
import React from 'react';
import { InputText } from './FormComponents';
import PropTypes from 'prop-types';

View File

@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useMemo, useRef } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import ReactDOMServer from 'react-dom/server';
import PropTypes from 'prop-types';

Some files were not shown because too many files have changed in this diff Show More