2022-03-21 02:59:26 -05:00
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
2024-01-01 02:43:48 -06:00
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
2022-03-21 02:59:26 -05:00
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext' ;
2024-06-06 06:43:12 -05:00
import { styled } from '@mui/material/styles' ;
2022-03-23 02:58:35 -05:00
import _ from 'lodash' ;
2022-03-21 02:59:26 -05:00
import url _for from 'sources/url_for' ;
2022-03-23 02:58:35 -05:00
import React , { useEffect , useMemo } from 'react' ;
2022-03-21 02:59:26 -05:00
import { FileType } from 'react-aspen' ;
2024-04-08 21:51:14 -05:00
import { Box } from '@mui/material' ;
2022-03-21 02:59:26 -05:00
import PropTypes from 'prop-types' ;
import SchemaView from '../../../../static/js/SchemaView' ;
import getApiInstance from '../../../../static/js/api_instance' ;
2024-04-08 21:51:14 -05:00
import CloseSharpIcon from '@mui/icons-material/CloseSharp' ;
import HelpIcon from '@mui/icons-material/HelpRounded' ;
import SaveSharpIcon from '@mui/icons-material/SaveSharp' ;
2022-03-21 02:59:26 -05:00
import pgAdmin from 'sources/pgadmin' ;
import { DefaultButton , PgIconButton , PrimaryButton } from '../../../../static/js/components/Buttons' ;
import BaseUISchema from 'sources/SchemaView/base_schema.ui' ;
import { getBinaryPathSchema } from '../../../../browser/server_groups/servers/static/js/binary_path.ui' ;
2023-10-23 07:13:17 -05:00
import usePreferences from '../store' ;
2022-03-21 02:59:26 -05:00
2024-06-06 06:43:12 -05:00
const StyledBox = styled ( Box ) ( ( { theme } ) => ( {
'& .PreferencesComponent-root' : {
display : 'flex' ,
flexDirection : 'column' ,
flexGrow : 1 ,
height : '100%' ,
backgroundColor : theme . palette . background . default ,
overflow : 'hidden' ,
'&$disabled' : {
color : '#ddd' ,
} ,
'& .PreferencesComponent-body' : {
borderColor : theme . otherVars . borderColor ,
display : 'flex' ,
flexGrow : 1 ,
height : '100%' ,
minHeight : 0 ,
overflow : 'hidden' ,
'& .PreferencesComponent-treeContainer' : {
flexBasis : '25%' ,
alignItems : 'flex-start' ,
paddingLeft : '5px' ,
minHeight : 0 ,
flexGrow : 1 ,
'& .PreferencesComponent-tree' : {
height : '100%' ,
flexGrow : 1
} ,
} ,
'& .PreferencesComponent-preferencesContainer' : {
flexBasis : '75%' ,
padding : '5px' ,
borderColor : theme . otherVars . borderColor + '!important' ,
borderLeft : '1px solid' ,
position : 'relative' ,
height : '100%' ,
paddingTop : '5px' ,
overflow : 'auto' ,
} ,
} ,
'& .PreferencesComponent-footer' : {
borderTop : ` 1px solid ${ theme . otherVars . inputBorderColor } !important ` ,
padding : '0.5rem' ,
display : 'flex' ,
width : '100%' ,
background : theme . otherVars . headerBg ,
'& .PreferencesComponent-actionBtn' : {
alignItems : 'flex-start' ,
} ,
'& .PreferencesComponent-buttonMargin' : {
marginLeft : '0.5em'
} ,
} ,
} ,
} ) ) ;
2022-03-21 02:59:26 -05:00
class PreferencesSchema extends BaseUISchema {
constructor ( initValues = { } , schemaFields = [ ] ) {
super ( {
... initValues
} ) ;
this . schemaFields = schemaFields ;
this . category = '' ;
}
get idAttribute ( ) {
return 'id' ;
}
setSelectedCategory ( category ) {
this . category = category ;
}
get baseFields ( ) {
return this . schemaFields ;
}
}
function RightPanel ( { schema , ... props } ) {
let initData = ( ) => new Promise ( ( resolve , reject ) => {
try {
resolve ( props . initValues ) ;
} catch ( error ) {
reject ( error ) ;
}
} ) ;
return (
< SchemaView
formType = { 'dialog' }
getInitData = { initData }
viewHelperProps = { { mode : 'edit' } }
schema = { schema }
showFooter = { false }
isTabView = { false }
onDataChange = { ( isChanged , changedData ) => {
props . onDataChange ( changedData ) ;
} }
/ >
) ;
}
RightPanel . propTypes = {
schema : PropTypes . object ,
initValues : PropTypes . object ,
onDataChange : PropTypes . func
} ;
export default function PreferencesComponent ( { ... props } ) {
2024-06-06 06:43:12 -05:00
2022-03-21 02:59:26 -05:00
const [ disableSave , setDisableSave ] = React . useState ( true ) ;
const prefSchema = React . useRef ( new PreferencesSchema ( { } , [ ] ) ) ;
const prefChangedData = React . useRef ( { } ) ;
const prefTreeInit = React . useRef ( false ) ;
const [ prefTreeData , setPrefTreeData ] = React . useState ( null ) ;
const [ initValues , setInitValues ] = React . useState ( { } ) ;
const [ loadTree , setLoadTree ] = React . useState ( 0 ) ;
const api = getApiInstance ( ) ;
2022-03-24 05:38:13 -05:00
const firstTreeElement = React . useRef ( '' ) ;
2023-10-23 07:13:17 -05:00
const preferencesStore = usePreferences ( ) ;
2022-03-21 02:59:26 -05:00
useEffect ( ( ) => {
const pref _url = url _for ( 'preferences.index' ) ;
api ( {
url : pref _url ,
method : 'GET' ,
} ) . then ( ( res ) => {
let preferencesData = [ ] ;
let preferencesTreeData = [ ] ;
let preferencesValues = { } ;
res . data . forEach ( node => {
2022-08-13 20:39:45 -05:00
let id = crypto . getRandomValues ( new Uint16Array ( 1 ) ) ;
2022-03-21 02:59:26 -05:00
let tdata = {
'id' : id . toString ( ) ,
'label' : node . label ,
'_label' : node . label ,
2024-03-14 07:42:28 -05:00
'name' : node . name ,
2022-03-21 02:59:26 -05:00
'icon' : '' ,
'inode' : true ,
'type' : 2 ,
'_type' : node . label . toLowerCase ( ) ,
'_id' : id ,
'_pid' : null ,
'childrenNodes' : [ ] ,
'expanded' : true ,
'isExpanded' : true ,
} ;
2022-03-24 05:38:13 -05:00
if ( firstTreeElement . current . length == 0 ) {
firstTreeElement . current = node . label ;
}
2022-03-21 02:59:26 -05:00
node . children . forEach ( subNode => {
2022-08-13 20:39:45 -05:00
let sid = crypto . getRandomValues ( new Uint16Array ( 1 ) ) ;
2022-03-21 02:59:26 -05:00
let nodeData = {
'id' : sid . toString ( ) ,
'label' : subNode . label ,
'_label' : subNode . label ,
2023-03-24 05:14:43 -05:00
'name' : subNode . name ,
2022-03-21 02:59:26 -05:00
'icon' : '' ,
'inode' : false ,
'_type' : subNode . label . toLowerCase ( ) ,
'_id' : sid ,
'_pid' : node . id ,
'type' : 1 ,
'expanded' : false ,
} ;
2022-03-23 02:58:35 -05:00
addNote ( node , subNode , nodeData , preferencesData ) ;
setPreferences ( node , subNode , nodeData , preferencesValues , preferencesData ) ;
2022-03-21 02:59:26 -05:00
tdata [ 'childrenNodes' ] . push ( nodeData ) ;
} ) ;
// set Preferences Tree data
preferencesTreeData . push ( tdata ) ;
} ) ;
setPrefTreeData ( preferencesTreeData ) ;
setInitValues ( preferencesValues ) ;
// set Preferences schema
prefSchema . current = new PreferencesSchema ( preferencesValues , preferencesData ) ;
} ) . catch ( ( err ) => {
2023-10-23 07:13:17 -05:00
pgAdmin . Browser . notifier . alert ( err ) ;
2022-03-21 02:59:26 -05:00
} ) ;
} , [ ] ) ;
2022-03-23 02:58:35 -05:00
function setPreferences ( node , subNode , nodeData , preferencesValues , preferencesData ) {
2022-03-29 05:57:33 -05:00
let addBinaryPathNote = false ;
2022-03-23 02:58:35 -05:00
subNode . preferences . forEach ( ( element ) => {
let note = '' ;
let type = getControlMappedForType ( element . type ) ;
if ( type === 'file' ) {
note = gettext ( 'Enter the directory in which the psql, pg_dump, pg_dumpall, and pg_restore utilities can be found for the corresponding database server version. The default path will be used for server versions that do not have a path specified.' ) ;
element . type = 'collection' ;
element . schema = getBinaryPathSchema ( ) ;
element . canAdd = false ;
element . canDelete = false ;
element . canEdit = false ;
element . editable = false ;
element . disabled = true ;
preferencesValues [ element . id ] = JSON . parse ( element . value ) ;
2022-03-29 05:57:33 -05:00
if ( addBinaryPathNote ) {
addNote ( node , subNode , nodeData , preferencesData , note ) ;
}
addBinaryPathNote = true ;
2022-03-23 02:58:35 -05:00
}
else if ( type == 'select' ) {
setControlProps ( element ) ;
element . type = type ;
preferencesValues [ element . id ] = element . value ;
setThemesOptions ( element ) ;
}
else if ( type === 'keyboardShortcut' ) {
getKeyboardShortcuts ( element , preferencesValues , node ) ;
} else if ( type === 'threshold' ) {
element . type = 'threshold' ;
let _val = element . value . split ( '|' ) ;
preferencesValues [ element . id ] = { 'warning' : _val [ 0 ] , 'alert' : _val [ 1 ] } ;
2022-03-24 05:38:13 -05:00
} else if ( subNode . label == gettext ( 'Results grid' ) && node . label == gettext ( 'Query Tool' ) ) {
2022-03-23 02:58:35 -05:00
setResultsOptions ( element , subNode , preferencesValues , type ) ;
} else {
element . type = type ;
preferencesValues [ element . id ] = element . value ;
}
delete element . value ;
element . visible = false ;
element . helpMessage = element ? . help _str ? element . help _str : null ;
preferencesData . push ( element ) ;
element . parentId = nodeData [ 'id' ] ;
} ) ;
}
function setResultsOptions ( element , subNode , preferencesValues , type ) {
if ( element . name == 'column_data_max_width' ) {
let size _control _id = null ;
subNode . preferences . forEach ( ( _el ) => {
if ( _el . name == 'column_data_auto_resize' ) {
size _control _id = _el . id ;
}
2022-04-07 07:06:56 -05:00
2022-03-23 02:58:35 -05:00
} ) ;
element . disabled = ( state ) => {
return state [ size _control _id ] != 'by_data' ;
} ;
}
element . type = type ;
preferencesValues [ element . id ] = element . value ;
}
function setThemesOptions ( element ) {
if ( element . name == 'theme' ) {
element . type = 'theme' ;
element . options . forEach ( ( opt ) => {
if ( opt . value == element . value ) {
opt . selected = true ;
} else {
opt . selected = false ;
}
} ) ;
}
}
function setControlProps ( element ) {
if ( element . control _props !== undefined ) {
element . controlProps = element . control _props ;
} else {
element . controlProps = { } ;
}
}
function getKeyboardShortcuts ( element , preferencesValues , node ) {
element . type = 'keyboardShortcut' ;
element . canAdd = false ;
element . canDelete = false ;
element . canEdit = false ;
element . editable = false ;
2023-10-23 07:13:17 -05:00
if ( preferencesStore . getPreferences ( node . label . toLowerCase ( ) , element . name ) ? . value ) {
let temp = preferencesStore . getPreferences ( node . label . toLowerCase ( ) , element . name ) . value ;
2022-03-23 02:58:35 -05:00
preferencesValues [ element . id ] = temp ;
} else {
preferencesValues [ element . id ] = element . value ;
}
}
function addNote ( node , subNode , nodeData , preferencesData , note = '' ) {
// Check and add the note for the element.
2022-03-24 05:38:13 -05:00
if ( subNode . label == gettext ( 'Nodes' ) && node . label == gettext ( 'Browser' ) ) {
2023-03-28 11:50:14 -05:00
note = [ gettext ( 'This settings is to Show/Hide nodes in the object explorer.' ) ] . join ( '' ) ;
2022-03-23 02:58:35 -05:00
} else {
2022-03-24 05:38:13 -05:00
note = [ note ] . join ( '' ) ;
2022-03-23 02:58:35 -05:00
}
if ( note && note . length > 0 ) {
2022-04-07 07:06:56 -05:00
//Add Note for Nodes
2022-03-23 02:58:35 -05:00
preferencesData . push (
{
id : _ . uniqueId ( 'note' ) + subNode . id ,
type : 'note' , text : note ,
visible : false ,
'parentId' : nodeData [ 'id' ]
} ,
) ;
}
}
2022-03-21 02:59:26 -05:00
2022-09-27 03:58:31 -05:00
function selectChildNode ( item , prefTreeInit ) {
if ( item . isExpanded && item . _children && item . _children . length > 0 && prefTreeInit . current && event . code !== 'ArrowUp' ) {
pgAdmin . Browser . ptree . tree . setActiveFile ( item . _children [ 0 ] , true ) ;
}
}
2022-03-21 02:59:26 -05:00
useEffect ( ( ) => {
let initTreeTimeout = null ;
2022-03-31 01:16:34 -05:00
let firstElement = null ;
2022-03-21 02:59:26 -05:00
// Listen selected preferences tree node event and show the appropriate components in right panel.
2022-03-31 01:16:34 -05:00
pgAdmin . Browser . Events . on ( 'preferences:tree:selected' , ( event , item ) => {
2022-03-21 02:59:26 -05:00
if ( item . type == FileType . File ) {
2023-03-24 05:14:43 -05:00
prefSchema . current . setSelectedCategory ( item . _metadata . data . name ) ;
2022-03-21 02:59:26 -05:00
prefSchema . current . schemaFields . forEach ( ( field ) => {
2023-03-06 05:33:47 -06:00
field . visible = field . parentId === item . _metadata . data . id && ! field ? . hidden ;
2022-03-31 01:16:34 -05:00
if ( field . visible && _ . isNull ( firstElement ) ) {
firstElement = field ;
}
2024-03-14 07:42:28 -05:00
field . labelTooltip = item . _parent . _metadata . data . name . toLowerCase ( ) + ':' + item . _metadata . data . name + ':' + field . name ;
2022-03-21 02:59:26 -05:00
} ) ;
2022-08-13 20:39:45 -05:00
setLoadTree ( crypto . getRandomValues ( new Uint16Array ( 1 ) ) ) ;
2022-03-23 02:58:35 -05:00
initTreeTimeout = setTimeout ( ( ) => {
2022-03-21 02:59:26 -05:00
prefTreeInit . current = true ;
2022-03-31 01:16:34 -05:00
if ( firstElement ) {
//set focus on first element on right side panel.
document . getElementsByName ( firstElement . id . toString ( ) ) [ 0 ] . focus ( ) ;
firstElement = '' ;
}
2022-03-21 02:59:26 -05:00
} , 10 ) ;
}
else {
2022-09-27 03:58:31 -05:00
selectChildNode ( item , prefTreeInit ) ;
2022-03-21 02:59:26 -05:00
}
} ) ;
// Listen open preferences tree node event to default select first child node on parent node selection.
2022-03-31 01:16:34 -05:00
pgAdmin . Browser . Events . on ( 'preferences:tree:opened' , ( event , item ) => {
2022-03-23 02:58:35 -05:00
pgAdmin . Browser . ptree . tree . setActiveFile ( item . _children [ 0 ] , true ) ;
2022-03-21 02:59:26 -05:00
} ) ;
// Listen added preferences tree node event to expand the newly added node on tree load.
2022-09-27 03:58:31 -05:00
pgAdmin . Browser . Events . on ( 'preferences:tree:added' , addPrefTreeNode ) ;
2022-03-21 02:59:26 -05:00
/* Clear the initTreeTimeout timeout if unmounted */
2022-03-23 02:58:35 -05:00
return ( ) => {
2022-03-21 02:59:26 -05:00
clearTimeout ( initTreeTimeout ) ;
} ;
2022-03-23 02:58:35 -05:00
} , [ ] ) ;
2022-03-21 02:59:26 -05:00
2022-09-27 03:58:31 -05:00
function addPrefTreeNode ( event , item ) {
if ( item . _parent . _fileName == firstTreeElement . current && item . _parent . isExpanded && ! prefTreeInit . current ) {
pgAdmin . Browser . ptree . tree . setActiveFile ( item . _parent . _children [ 0 ] , true ) ;
}
else if ( item . type == FileType . Directory ) {
// Check the if newely added node is Directoy and call toggle to expand the node.
pgAdmin . Browser . ptree . tree . toggleDirectory ( item ) ;
}
}
2022-03-21 02:59:26 -05:00
function getControlMappedForType ( type ) {
switch ( type ) {
case 'text' :
return 'text' ;
case 'input' :
return 'text' ;
case 'boolean' :
return 'switch' ;
case 'node' :
return 'switch' ;
case 'integer' :
return 'numeric' ;
case 'numeric' :
return 'numeric' ;
case 'date' :
return 'datetimepicker' ;
case 'datetime' :
return 'datetimepicker' ;
case 'options' :
return 'select' ;
case 'select' :
return 'select' ;
case 'select2' :
return 'select' ;
case 'multiline' :
return 'multiline' ;
case 'switch' :
return 'switch' ;
case 'keyboardshortcut' :
return 'keyboardShortcut' ;
case 'radioModern' :
return 'toggle' ;
case 'selectFile' :
return 'file' ;
case 'threshold' :
return 'threshold' ;
default :
2024-01-25 05:21:40 -06:00
if ( console ? . warn ) {
2022-03-21 02:59:26 -05:00
// Warning for developer only.
console . warn (
'Hmm.. We don\'t know how to render this type - \'\'' + type + '\' of control.'
) ;
}
return 'input' ;
}
}
2022-03-23 02:58:35 -05:00
function getCollectionValue ( _metadata , value , initVals ) {
2022-03-21 02:59:26 -05:00
let val = value ;
if ( typeof ( value ) == 'object' ) {
if ( _metadata [ 0 ] . type == 'collection' && _metadata [ 0 ] . schema ) {
if ( 'binaryPath' in value . changed [ 0 ] ) {
let pathData = [ ] ;
let pathVersions = [ ] ;
value . changed . forEach ( ( chValue ) => {
pathVersions . push ( chValue . version ) ;
} ) ;
2022-03-23 02:58:35 -05:00
getPathData ( initVals , pathData , _metadata , value , pathVersions ) ;
2022-03-21 02:59:26 -05:00
val = JSON . stringify ( pathData ) ;
} else {
let key _val = {
'char' : value . changed [ 0 ] [ 'key' ] ,
'key_code' : value . changed [ 0 ] [ 'code' ] ,
} ;
value . changed [ 0 ] [ 'key' ] = key _val ;
val = value . changed [ 0 ] ;
}
} else if ( 'warning' in value ) {
val = value [ 'warning' ] + '|' + value [ 'alert' ] ;
} else if ( value ? . changed && value . changed . length > 0 ) {
val = JSON . stringify ( value . changed ) ;
}
}
return val ;
}
2022-03-23 02:58:35 -05:00
function getPathData ( initVals , pathData , _metadata , value , pathVersions ) {
initVals [ _metadata [ 0 ] . id ] . forEach ( ( initVal ) => {
if ( pathVersions . includes ( initVal . version ) ) {
pathData . push ( value . changed [ pathVersions . indexOf ( initVal . version ) ] ) ;
}
else {
pathData . push ( initVal ) ;
}
} ) ;
}
function savePreferences ( data , initVal ) {
2022-03-21 02:59:26 -05:00
let _data = [ ] ;
for ( const [ key , value ] of Object . entries ( data . current ) ) {
let _metadata = prefSchema . current . schemaFields . filter ( ( el ) => { return el . id == key ; } ) ;
if ( _metadata . length > 0 ) {
2022-03-23 02:58:35 -05:00
let val = getCollectionValue ( _metadata , value , initVal ) ;
2022-03-21 02:59:26 -05:00
_data . push ( {
'category_id' : _metadata [ 0 ] [ 'cid' ] ,
'id' : parseInt ( key ) ,
'mid' : _metadata [ 0 ] [ 'mid' ] ,
'name' : _metadata [ 0 ] [ 'name' ] ,
'value' : val ,
} ) ;
}
}
if ( _data . length > 0 ) {
save ( _data , data ) ;
}
}
function checkRefreshRequired ( pref , requires _refresh ) {
if ( pref . name == 'user_language' ) {
requires _refresh = true ;
}
return requires _refresh ;
}
function save ( save _data , data ) {
api ( {
url : url _for ( 'preferences.index' ) ,
method : 'PUT' ,
data : save _data ,
} ) . then ( ( ) => {
2023-05-23 04:07:16 -05:00
let requiresTreeRefresh = save _data . some ( ( s ) => {
2023-06-02 00:29:47 -05:00
return s . name == 'show_system_objects' || s . name == 'show_empty_coll_nodes' || s . name . startsWith ( 'show_node_' ) || s . name == 'hide_shared_server' || s . name == 'show_user_defined_templates' ;
2023-05-23 04:07:16 -05:00
} ) ;
2022-03-21 02:59:26 -05:00
let requires _refresh = false ;
for ( const [ key ] of Object . entries ( data . current ) ) {
2023-10-23 07:13:17 -05:00
let pref = preferencesStore . getPreferenceForId ( Number ( key ) ) ;
2022-03-21 02:59:26 -05:00
requires _refresh = checkRefreshRequired ( pref , requires _refresh ) ;
}
2023-05-23 04:07:16 -05:00
if ( requiresTreeRefresh ) {
2023-10-23 07:13:17 -05:00
pgAdmin . Browser . notifier . confirm (
2023-05-24 00:56:02 -05:00
gettext ( 'Object explorer refresh required' ) ,
gettext ( 'An object explorer refresh is required. Do you wish to refresh it now?' ) ,
2023-05-23 04:07:16 -05:00
function ( ) {
2024-04-26 01:29:53 -05:00
pgAdmin . Browser . tree . destroy ( ) . then (
( ) => {
pgAdmin . Browser . Events . trigger ( 'pgadmin-browser:tree:destroyed' , undefined , undefined ) ;
2023-05-23 04:07:16 -05:00
return true ;
2024-04-26 01:29:53 -05:00
}
) ;
2023-05-23 04:07:16 -05:00
} ,
function ( ) {
return true ;
} ,
gettext ( 'Refresh' ) ,
gettext ( 'Later' )
) ;
}
2022-03-21 02:59:26 -05:00
if ( requires _refresh ) {
2023-10-23 07:13:17 -05:00
pgAdmin . Browser . notifier . confirm (
2022-03-21 02:59:26 -05:00
gettext ( 'Refresh required' ) ,
gettext ( 'A page refresh is required to apply the theme. Do you wish to refresh the page now?' ) ,
function ( ) {
/* If user clicks Yes */
location . reload ( ) ;
return true ;
} ,
2022-03-23 02:58:35 -05:00
function ( ) { props . closeModal ( ) ; } ,
2022-03-21 02:59:26 -05:00
gettext ( 'Refresh' ) ,
gettext ( 'Later' )
) ;
}
// Refresh preferences cache
2023-10-23 07:13:17 -05:00
preferencesStore . cache ( ) ;
2022-03-23 02:58:35 -05:00
props . closeModal ( ) ;
2022-03-21 02:59:26 -05:00
} ) . catch ( ( err ) => {
2023-10-23 07:13:17 -05:00
pgAdmin . Browser . notifier . alert ( err . response . data ) ;
2022-03-21 02:59:26 -05:00
} ) ;
}
const onDialogHelp = ( ) => {
window . open ( url _for ( 'help.static' , { 'filename' : 'preferences.html' } ) , 'pgadmin_help' ) ;
} ;
return (
2024-06-06 06:43:12 -05:00
< StyledBox height = { '100%' } >
< Box className = 'PreferencesComponent-root' >
< Box className = 'PreferencesComponent-body' >
< Box className = 'PreferencesComponent-treeContainer' >
< Box className = 'PreferencesComponent-tree' id = { 'treeContainer' } tabIndex = { 0 } >
2022-03-23 02:58:35 -05:00
{
useMemo ( ( ) => ( prefTreeData && props . renderTree ( prefTreeData ) ) , [ prefTreeData ] )
}
< / Box >
2022-03-21 02:59:26 -05:00
< / Box >
2024-06-06 06:43:12 -05:00
< Box className = 'PreferencesComponent-preferencesContainer' >
2022-03-21 02:59:26 -05:00
{
2023-03-24 05:14:43 -05:00
prefSchema . current && loadTree > 0 &&
2022-03-21 02:59:26 -05:00
< RightPanel schema = { prefSchema . current } initValues = { initValues } onDataChange = { ( changedData ) => {
Object . keys ( changedData ) . length > 0 ? setDisableSave ( false ) : setDisableSave ( true ) ;
prefChangedData . current = changedData ;
} } > < / RightPanel >
}
< / Box >
< / Box >
2024-06-06 06:43:12 -05:00
< Box className = 'PreferencesComponent-footer' >
2022-03-21 02:59:26 -05:00
< Box >
< PgIconButton data - test = "dialog-help" onClick = { onDialogHelp } icon = { < HelpIcon / > } title = { gettext ( 'Help for this dialog.' ) } / >
< / Box >
2024-06-06 06:43:12 -05:00
< Box className = 'PreferencesComponent-actionBtn' marginLeft = "auto" >
< DefaultButton className = 'PreferencesComponent-buttonMargin' onClick = { ( ) => { props . closeModal ( ) ; } } startIcon = { < CloseSharpIcon onClick = { ( ) => { props . closeModal ( ) ; } } / > } >
2022-03-21 02:59:26 -05:00
{ gettext ( 'Cancel' ) }
< / DefaultButton >
2024-06-06 06:43:12 -05:00
< PrimaryButton className = 'PreferencesComponent-buttonMargin' startIcon = { < SaveSharpIcon / > } disabled = { disableSave } onClick = { ( ) => { savePreferences ( prefChangedData , initValues ) ; } } >
2022-03-21 02:59:26 -05:00
{ gettext ( 'Save' ) }
< / PrimaryButton >
< / Box >
< / Box >
< / B o x >
2024-06-06 06:43:12 -05:00
< / StyledBox >
2022-03-21 02:59:26 -05:00
) ;
}
PreferencesComponent . propTypes = {
schema : PropTypes . array ,
initValues : PropTypes . object ,
closeModal : PropTypes . func ,
renderTree : PropTypes . func
} ;