Don't show 'Types of objects' for the 'Cluster' operation. Fixes #7884

This commit is contained in:
Ashesh Vashi 2024-09-18 07:48:09 +05:30 committed by GitHub
parent a361fd94ff
commit 441cc57bb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 132 additions and 104 deletions

View File

@ -16,14 +16,15 @@ class TokenHeaderSchema extends BaseUISchema {
constructor(tokenOptions) { constructor(tokenOptions) {
super({ super({
token: undefined, token: undefined,
isNew: false,
}); });
this.tokenOptions = tokenOptions; this.tokenOptions = tokenOptions;
this.isNewFTSConf = true;
} }
addDisabled() { set isNewFTSConf(flag) {
return this.isNewFTSConf; if (!this.state) return;
this.state.data = {...this.state.data, isNew: flag};
} }
getNewData(data) { getNewData(data) {
@ -36,8 +37,14 @@ class TokenHeaderSchema extends BaseUISchema {
get baseFields() { get baseFields() {
let obj = this; let obj = this;
return [{ return [{
id: 'token', label: gettext('Tokens'), type:'select', editable: false, id: 'token', label: gettext('Tokens'), deps: ['isNew'],
options: this.tokenOptions, disabled: function() { return obj.isNewFTSConf; } type: () => ({
type: 'select',
options: this.tokenOptions,
}),
disabled: function() { return obj.isNewFTSConf; }
}, {
id: 'isNew', visible: false, type: 'text',
}]; }];
} }
} }

View File

@ -13,10 +13,15 @@ import BaseUISchema from 'sources/SchemaView/base_schema.ui';
export default class RuleSchema extends BaseUISchema { export default class RuleSchema extends BaseUISchema {
constructor(fieldOptions={}) { constructor(fieldOptions={}) {
const schemaNode = fieldOptions?.nodeInfo['schema'];
const schema = schemaNode?.label || '';
const view = fieldOptions?.nodeData?.label;
super({ super({
oid: undefined, oid: undefined,
name: undefined, name: undefined,
schema: undefined schema: schema,
view: view,
}); });
this.fieldOptions = { this.fieldOptions = {
@ -42,7 +47,11 @@ export default class RuleSchema extends BaseUISchema {
if (state.name == '_RETURN') { if (state.name == '_RETURN') {
return true; return true;
} }
return !(obj.isNew(state) || obj.fieldOptions.nodeInfo.server.version >= 90400);
return !(
obj.isNew(state) ||
obj.fieldOptions.nodeInfo.server.version >= 90400
);
}, noEmpty: true }, noEmpty: true
}, },
{ {
@ -50,25 +59,18 @@ export default class RuleSchema extends BaseUISchema {
type: 'text', mode: ['properties'], type: 'text', mode: ['properties'],
}, },
{ {
id: 'schema', label:'', id: 'schema', label:'', type: 'text', visible: false,
type: 'text', visible: false, disabled: (state) => {
// It is used while generating sql
state.schema = ('schema' in obj.fieldOptions.nodeInfo) ? obj.fieldOptions.nodeInfo.schema.label : '';
},
}, },
{ {
id: 'view', label:'', id: 'view', label:'', type: 'text', visible: false,
type: 'text', visible: false, disabled: (state) => {
// It is used while generating sql
state.view = obj.fieldOptions.nodeData.label;
},
}, },
{ {
id: 'is_enable_rule', label: gettext('Rule enabled?'), id: 'is_enable_rule', label: gettext('Rule enabled?'),
mode: ['edit', 'properties'], group: gettext('Definition'), mode: ['edit', 'properties'], group: gettext('Definition'),
type: 'select', type: 'select',
disabled: () => { disabled: () => {
return 'catalog' in obj.fieldOptions.nodeInfo || 'view' in obj.fieldOptions.nodeInfo; return 'catalog' in obj.fieldOptions.nodeInfo ||
'view' in obj.fieldOptions.nodeInfo;
}, },
options: [ options: [
{label: gettext('Enable'), value: 'O'}, {label: gettext('Enable'), value: 'O'},
@ -90,13 +92,12 @@ export default class RuleSchema extends BaseUISchema {
], ],
}, },
{ {
id: 'do_instead', label: gettext('Do instead?'), group: gettext('Definition'), id: 'do_instead', label: gettext('Do instead?'), type: 'switch',
type: 'switch', group: gettext('Definition'),
}, },
{ {
id: 'condition', label: gettext('Condition'), id: 'condition', label: gettext('Condition'),
type: 'sql', isFullTab: true, group: gettext('Condition'), type: 'sql', isFullTab: true, group: gettext('Condition'),
}, },
{ {
id: 'statements', label: gettext('Commands'), id: 'statements', label: gettext('Commands'),
@ -107,7 +108,8 @@ export default class RuleSchema extends BaseUISchema {
type: 'switch', mode: ['properties'], type: 'switch', mode: ['properties'],
}, },
{ {
id: 'comment', label: gettext('Comment'), cell: 'text', type: 'multiline', id: 'comment', label: gettext('Comment'), cell: 'text',
type: 'multiline',
}, },
]; ];
} }

View File

@ -165,6 +165,8 @@ export default class RoleSchema extends BaseUISchema {
disabled: obj.readOnly, disabled: obj.readOnly,
mode: ['edit', 'create'], cell: 'text', mode: ['edit', 'create'], cell: 'text',
type: 'collection', type: 'collection',
canDelete: (state) => !obj.readOnly(state),
canDeleteRow: true,
schema: obj.membershipSchema, schema: obj.membershipSchema,
helpMessage: obj.isReadOnly ? gettext('Select the checkbox for roles to include WITH ADMIN OPTION.') : gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.'), helpMessage: obj.isReadOnly ? gettext('Select the checkbox for roles to include WITH ADMIN OPTION.') : gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.'),
}, },
@ -185,7 +187,9 @@ export default class RoleSchema extends BaseUISchema {
type: 'collection', type: 'collection',
schema: obj.membershipSchema, schema: obj.membershipSchema,
disabled: obj.readOnly, disabled: obj.readOnly,
helpMessage: obj.isReadOnly ? gettext('Select the checkbox for roles to include WITH ADMIN OPTION.') : gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.') , canDelete: (state) => !obj.readOnly(state),
canDeleteRow: true,
helpMessage: obj.isReadOnly ? gettext('Select the checkbox for roles to include WITH ADMIN OPTION.') : gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.'),
}, },
{ {
id: 'rolmembers', label: gettext('Members'), group: gettext('Membership'), id: 'rolmembers', label: gettext('Members'), group: gettext('Membership'),

View File

@ -101,31 +101,34 @@ class AzureCredSchema extends BaseUISchema {
helpMessage: gettext( helpMessage: gettext(
'After clicking the button above you will be redirected to the Microsoft Azure authentication page in a new browser tab if the Interactive Browser option is selected.' 'After clicking the button above you will be redirected to the Microsoft Azure authentication page in a new browser tab if the Interactive Browser option is selected.'
), ),
depChange: (state, source)=> { onClick: () => {
if(source == 'auth_type' || source == 'azure_tenant_id'){ const schemaState = obj.state;
return {is_authenticated: false, auth_code: ''}; if (!schemaState) return;
}
if(source == 'auth_btn') { const state = schemaState.data;
return {is_authenticating: true}; const setSchemaData = (data) => {
} schemaState.data = {...schemaState.data, ...data};
}, };
deferredDepChange: (state, source)=>{
return new Promise((resolve, reject)=>{ setTimeout(() => {
/* button clicked */ setSchemaData({is_authenticating: true});
if(source == 'auth_btn') {
obj.fieldOptions.authenticateAzure(state.auth_type, state.azure_tenant_id) obj.fieldOptions.authenticateAzure(
.then(()=>{ state.auth_type, state.azure_tenant_id
resolve(()=>({ ).then(() => {
setSchemaData({
is_authenticated: true, is_authenticated: true,
is_authenticating: false, is_authenticating: false,
auth_code: '' auth_code: ''
}));
})
.catch((err)=>{
reject(err instanceof Error ? err : Error(gettext('Something went wrong')));
}); });
} }).catch((err) => {
// TODO:: Show error message.
console.error(
err instanceof Error ?
err : Error(gettext('Something went wrong'))
);
}); });
}, 0);
}, },
disabled: (state)=> { disabled: (state)=> {
if(state.auth_type == 'interactive_browser_credential' && state.azure_tenant_id == ''){ if(state.auth_type == 'interactive_browser_credential' && state.azure_tenant_id == ''){

View File

@ -55,33 +55,30 @@ class GoogleCredSchema extends BaseUISchema{
disabled: (state)=>{ disabled: (state)=>{
return !state.client_secret_file; return !state.client_secret_file;
}, },
deferredDepChange: (state, source)=>{ onClick: () => {
return new Promise((resolve, reject)=>{ const schemaState = obj.state;
/* button clicked */ if (!schemaState) return;
if(source == 'auth_btn') {
obj.fieldOptions.authenticateGoogle(state.client_secret_file)
.then((apiRes)=>{
resolve(()=>{
if(apiRes){
obj.fieldOptions.verification_ack()
.then(()=>{
resolve();
})
.catch((err)=>{
reject(err instanceof Error ? err : Error(gettext('Something went wrong')));
});
}
});
})
.catch((err)=>{
reject(err instanceof Error ? err : Error(gettext('Something went wrong')));
});
}
});
}
}
];}
const state = schemaState.data;
setTimeout(() => {
obj.fieldOptions.authenticateGoogle(state.client_secret_file)
.then((apiRes) => {
if(apiRes) {
obj.fieldOptions.verification_ack();
}
}).catch((err) => {
// FIXME:: Show error message.
console.error(
err instanceof Error ?
err : Error(gettext('Something went wrong'))
);
});
}, 0);
},
},
];
}
} }
class GoogleProjectDetailsSchema extends BaseUISchema { class GoogleProjectDetailsSchema extends BaseUISchema {

View File

@ -242,6 +242,10 @@ export default function ObjectNodeProperties({panelId, node, treeNodeInfo, nodeD
return nodeData?._id + '-' + staleCounter.current; return nodeData?._id + '-' + staleCounter.current;
}, [isActive, nodeData?._id, isStale]); }, [isActive, nodeData?._id, isStale]);
if(!isActive && actionType == 'properties') {
return <></>;
}
/* Fire at will, mount the DOM */ /* Fire at will, mount the DOM */
return ( return (
<SchemaView <SchemaView

View File

@ -36,6 +36,19 @@ const StyledBox = styled(Box)(({theme}) => ({
'& .DataGridFormHeader-border': { '& .DataGridFormHeader-border': {
...theme.mixins.panelBorder, ...theme.mixins.panelBorder,
borderBottom: 0, borderBottom: 0,
'& .DataGridFormHeader-gridHeader': {
display: 'flex',
flexWrap: 'wrap',
},
'& .DataGridView-gridHeaderText': {
padding: theme.spacing(0.5, 1),
fontWeight: theme.typography.fontWeightBold,
},
'& .DataGridFormHeader-gridHeader-search': {
flex: 1,
padding: 0,
display: 'flex',
},
'& .DataGridFormHeader-body': { '& .DataGridFormHeader-body': {
padding: '0', padding: '0',
backgroundColor: theme.palette.grey[400], backgroundColor: theme.palette.grey[400],
@ -125,9 +138,9 @@ export function DataGridFormHeader({tableEleRef}) {
return ( return (
<StyledBox> <StyledBox>
<Box className='DataGridFormHeader-border'> <Box className='DataGridFormHeader-border'>
<Box className='DataGridView-gridHeader'> <Box className='DataGridFormHeader-gridHeader'>
{label && <Box className='DataGridView-gridHeaderText'>{label}</Box>} {label && <Box className='DataGridView-gridHeaderText'>{label}</Box>}
<Box className='DataGridView-gridHeaderText' style={{flex: 1}}> <Box className='DataGridFormHeader-gridHeader-search'>
<SearchBox/> <SearchBox/>
</Box> </Box>
</Box> </Box>

View File

@ -43,7 +43,9 @@ export function getMappedCell({field}) {
subscriberManager.current?.signal(...args); subscriberManager.current?.signal(...args);
}; };
listenDepChanges(
const depVals = listenDepChanges(
colAccessPath, field, schemaState, rerenderCellOnDepChange colAccessPath, field, schemaState, rerenderCellOnDepChange
); );
@ -98,13 +100,9 @@ export function getMappedCell({field}) {
props.cell = 'unknown'; props.cell = 'unknown';
} }
const memDeps = [
...flatternObject(colOptions), value, row.index,
field?.deps?.map((dep) => rowValue[dep])
];
return useMemo( return useMemo(
() => <MappedCellControl {...props}/>, memDeps () => <MappedCellControl {...props}/>,
[...(depVals || []), ...flatternObject(colOptions), value, row.index]
); );
}; };

View File

@ -101,6 +101,7 @@ export default function FormView({
'select:not(disabled)', 'select:not(disabled)',
'textarea', 'textarea',
'[tabindex]:not([tabindex="-1"]):not([data-test="tabpanel"])', '[tabindex]:not([tabindex="-1"]):not([data-test="tabpanel"])',
'div[class="cm-content"]:not([aria-readonly="true"])',
].join(', ')); ].join(', '));
if (firstFocussableElement) firstFocussableElement.focus(); if (firstFocussableElement) firstFocussableElement.focus();

View File

@ -7,7 +7,7 @@
// //
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
import React, { useEffect, useMemo } from 'react'; import React, { useState, useEffect, useMemo } from 'react';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done'; import DoneIcon from '@mui/icons-material/Done';
@ -47,6 +47,7 @@ export default function SchemaDialogView({
}) { }) {
// View helper properties // View helper properties
const onDataChange = props.onDataChange; const onDataChange = props.onDataChange;
const [resetKey, setResetKey] = useState(0);
// Schema data state manager // Schema data state manager
const {schemaState, dataDispatch, reset} = useSchemaState({ const {schemaState, dataDispatch, reset} = useSchemaState({
@ -55,6 +56,11 @@ export default function SchemaDialogView({
loadingText, loadingText,
}); });
const resetView = () => {
reset();
setResetKey(Date.now());
};
// Is saving operation in progress? // Is saving operation in progress?
const setSaving = (val) => schemaState.isSaving = val; const setSaving = (val) => schemaState.isSaving = val;
const setLoaderText = (val) => schemaState.setMessage(val); const setLoaderText = (val) => schemaState.setMessage(val);
@ -68,26 +74,13 @@ export default function SchemaDialogView({
const Notifier = props.Notifier || pgAdmin.Browser.notifier; const Notifier = props.Notifier || pgAdmin.Browser.notifier;
useEffect(() => { useEffect(() => {
/*
* Docker on load focusses itself, so our focus should execute later.
*/
let focusTimeout = setTimeout(()=>{
}, 250);
// Clear the focus timeout if unmounted.
return () => {
clearTimeout(focusTimeout);
};
}, []);
useEffect(()=>{
if (!props.resetKey) return; if (!props.resetKey) return;
reset(); resetView();
}, [props.resetKey]); }, [props.resetKey]);
const onResetClick = () => { const onResetClick = () => {
const resetIt = () => { const resetIt = () => {
reset(); resetView();
return true; return true;
}; };
@ -194,7 +187,7 @@ export default function SchemaDialogView({
hasSQLTab={props.hasSQL} getSQLValue={getSQLValue} hasSQLTab={props.hasSQL} getSQLValue={getSQLValue}
isTabView={isTabView} isTabView={isTabView}
className={props.formClassName} className={props.formClassName}
showError={true} resetKey={props.resetKey} showError={true} resetKey={resetKey}
focusOnFirstInput={true} focusOnFirstInput={true}
/> />
</Box> </Box>
@ -235,7 +228,7 @@ export default function SchemaDialogView({
</Box> </Box>
} }
</SchemaStateContext.Provider> </SchemaStateContext.Provider>
</StyledBox>, [schema._id, viewHelperProps.mode] </StyledBox>, [schema._id, viewHelperProps.mode, resetKey]
); );
} }

View File

@ -64,7 +64,9 @@ export const sessDataReducer = (state, action) => {
_.set(data, action.path, action.value); _.set(data, action.path, action.value);
// If there is any dep listeners get the changes. // If there is any dep listeners get the changes.
data = getDepChange(action.path, data, state, action); data = getDepChange(action.path, data, state, action);
deferredList = getDeferredDepChange(action.path, data, state, action); deferredList = getDeferredDepChange(
action.path, _.cloneDeep(data), state, action
);
data.__deferred__ = deferredList || []; data.__deferred__ = deferredList || [];
break; break;

View File

@ -76,7 +76,7 @@ export const createFieldControls = ({
const { visible } = schemaState.options(accessPath.concat(field.id)); const { visible } = schemaState.options(accessPath.concat(field.id));
currentGroup = createGroup( currentGroup = createGroup(
field.id, field.label, visible, field, true field.id, field.group || field.label, visible, field, true
); );
} else { } else {
const { group } = field; const { group } = field;

View File

@ -31,11 +31,14 @@ export const SearchInputText = ({
placeholder: placeholder || gettext('Search'), placeholder: placeholder || gettext('Search'),
style: { style: {
width: size == SEARCH_INPUT_SIZE.FULL ? '100%' : '50%', width: size == SEARCH_INPUT_SIZE.FULL ? '100%' : '50%',
float: alignment == SEARCH_INPUT_ALIGNMENT.RIGHT ? 'right' : 'left',
}, },
value: searchText, value: searchText,
onChange, onChange,
}; };
if (alignment == SEARCH_INPUT_ALIGNMENT.RIGHT)
props.style['margin-left'] = 'auto';
else
props.style['margin-right'] = 'auto';
return <InputText {...props}/>; return <InputText {...props}/>;
}; };

View File

@ -395,6 +395,7 @@ export default class MaintenanceSchema extends BaseUISchema {
label: gettext('Type of objects'), label: gettext('Type of objects'),
schema: obj.getVacuumSchema(), schema: obj.getVacuumSchema(),
group: gettext('Options'), group: gettext('Options'),
deps: ['op'],
visible: function(state) { visible: function(state) {
if (state?.op == 'ANALYZE') { if (state?.op == 'ANALYZE') {
return obj?.nodeInfo?.server?.version >= 120000; return obj?.nodeInfo?.server?.version >= 120000;