mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-01-09 23:54:09 -06:00
Stability and bug fixes in schemaview react framework.
This commit is contained in:
parent
e3992527fb
commit
bb5e2b98e9
@ -179,19 +179,19 @@ function DataTableRow({row, totalRows, isResizing, schema, schemaRef, accessPath
|
||||
schema.fields.forEach((field)=>{
|
||||
/* Self change is also dep change */
|
||||
if(field.depChange) {
|
||||
depListener.addDepListener(accessPath.concat(field.id), accessPath.concat(field.id), field.depChange);
|
||||
depListener?.addDepListener(accessPath.concat(field.id), accessPath.concat(field.id), field.depChange);
|
||||
}
|
||||
(evalFunc(null, field.deps) || []).forEach((dep)=>{
|
||||
let source = accessPath.concat(dep);
|
||||
if(_.isArray(dep)) {
|
||||
source = dep;
|
||||
}
|
||||
depListener.addDepListener(source, accessPath.concat(field.id), field.depChange);
|
||||
depListener?.addDepListener(source, accessPath.concat(field.id), field.depChange);
|
||||
});
|
||||
});
|
||||
return ()=>{
|
||||
/* Cleanup the listeners when unmounting */
|
||||
depListener.removeDepListener(accessPath);
|
||||
depListener?.removeDepListener(accessPath);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@ -324,7 +324,7 @@ export default function DataGridView({
|
||||
return 0;
|
||||
}).map((field)=>{
|
||||
let colInfo = {
|
||||
Header: field.label,
|
||||
Header: field.label||<> </>,
|
||||
accessor: field.id,
|
||||
field: field,
|
||||
resizable: true,
|
||||
@ -386,12 +386,8 @@ export default function DataGridView({
|
||||
);
|
||||
|
||||
const onAddClick = useCallback(()=>{
|
||||
if(props.canAddRow) {
|
||||
let state = schemaRef.current.top ? schemaRef.current.top.sessData : schemaRef.current.sessData;
|
||||
let canAddRow = evalFunc(schemaRef.current, props.canAddRow, state || {});
|
||||
if(!canAddRow) {
|
||||
return;
|
||||
}
|
||||
if(!props.canAddRow) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newRow = schemaRef.current.getNewData();
|
||||
@ -490,7 +486,7 @@ DataGridView.propTypes = {
|
||||
formErr: PropTypes.object,
|
||||
schema: CustomPropTypes.schemaUI,
|
||||
accessPath: PropTypes.array.isRequired,
|
||||
dataDispatch: PropTypes.func.isRequired,
|
||||
dataDispatch: PropTypes.func,
|
||||
containerClassName: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
||||
fixedRows: PropTypes.oneOfType([PropTypes.array, PropTypes.instanceOf(Promise), PropTypes.func]),
|
||||
columns: PropTypes.array,
|
||||
|
@ -80,6 +80,7 @@ export function getFieldMetaData(field, schema, value, viewHelperProps, onlyMode
|
||||
canEdit: false,
|
||||
canDelete: true,
|
||||
modeSupported: true,
|
||||
canAddRow: true,
|
||||
};
|
||||
|
||||
if(field.mode) {
|
||||
@ -115,11 +116,11 @@ export function getFieldMetaData(field, schema, value, viewHelperProps, onlyMode
|
||||
|
||||
retData.disabled = Boolean(evalFunc(schema, disabled, value));
|
||||
|
||||
let {canAdd, canEdit, canDelete } = field;
|
||||
let {canAdd, canEdit, canDelete, canAddRow } = field;
|
||||
retData.canAdd = _.isUndefined(canAdd) ? retData.canAdd : evalFunc(schema, canAdd, value);
|
||||
retData.canEdit = _.isUndefined(canEdit) ? retData.canEdit : evalFunc(schema, canEdit, value);
|
||||
retData.canDelete = _.isUndefined(canDelete) ? retData.canDelete : evalFunc(schema, canDelete, value);
|
||||
|
||||
retData.canAddRow = _.isUndefined(canAddRow) ? retData.canAddRow : evalFunc(schema, canAddRow, value);
|
||||
return retData;
|
||||
}
|
||||
|
||||
@ -137,6 +138,7 @@ export default function FormView({
|
||||
const onScreenTracker = useRef(false);
|
||||
const depListener = useContext(DepListenerContext);
|
||||
let groupLabels = {};
|
||||
const schemaRef = useRef(schema);
|
||||
|
||||
let isOnScreen = useOnScreen(formRef);
|
||||
if(isOnScreen) {
|
||||
@ -153,7 +155,7 @@ export default function FormView({
|
||||
useEffect(()=>{
|
||||
/* Calculate the fields which depends on the current field */
|
||||
if(!isDataGridForm) {
|
||||
schema.fields.forEach((field)=>{
|
||||
schemaRef.current.fields.forEach((field)=>{
|
||||
/* Self change is also dep change */
|
||||
if(field.depChange || field.deferredDepChange) {
|
||||
depListener.addDepListener(accessPath.concat(field.id), accessPath.concat(field.id), field.depChange, field.deferredDepChange);
|
||||
@ -178,8 +180,8 @@ export default function FormView({
|
||||
let fullTabs = [];
|
||||
|
||||
/* Prepare the array of components based on the types */
|
||||
schema.fields.forEach((field)=>{
|
||||
let {visible, disabled, readonly, canAdd, canEdit, canDelete, modeSupported} =
|
||||
schemaRef.current.fields.forEach((field)=>{
|
||||
let {visible, disabled, readonly, canAdd, canEdit, canDelete, canAddRow, modeSupported} =
|
||||
getFieldMetaData(field, schema, value, viewHelperProps);
|
||||
|
||||
if(modeSupported) {
|
||||
@ -192,7 +194,7 @@ export default function FormView({
|
||||
if(field.type === 'nested-tab') {
|
||||
/* Pass on the top schema */
|
||||
if(isNested) {
|
||||
field.schema.top = schema.top;
|
||||
field.schema.top = schemaRef.current.top;
|
||||
} else {
|
||||
field.schema.top = schema;
|
||||
}
|
||||
@ -204,7 +206,7 @@ export default function FormView({
|
||||
} else if(field.type === 'nested-fieldset') {
|
||||
/* Pass on the top schema */
|
||||
if(isNested) {
|
||||
field.schema.top = schema.top;
|
||||
field.schema.top = schemaRef.current.top;
|
||||
} else {
|
||||
field.schema.top = schema;
|
||||
}
|
||||
@ -219,9 +221,9 @@ export default function FormView({
|
||||
let depsMap = [value[field.id]];
|
||||
/* Pass on the top schema */
|
||||
if(isNested) {
|
||||
field.schema.top = schema.top;
|
||||
field.schema.top = schemaRef.current.top;
|
||||
} else {
|
||||
field.schema.top = schema;
|
||||
field.schema.top = schemaRef.current;
|
||||
}
|
||||
|
||||
depsMap.push(canAdd, canEdit, canDelete, visible);
|
||||
@ -235,7 +237,7 @@ export default function FormView({
|
||||
key: field.id, value: value[field.id], viewHelperProps: viewHelperProps, formErr: formErr,
|
||||
schema: field.schema, accessPath: accessPath.concat(field.id), dataDispatch: dataDispatch,
|
||||
containerClassName: classes.controlRow, ...field, canAdd: canAdd, canEdit: canEdit, canDelete: canDelete,
|
||||
visible: visible,
|
||||
visible: visible, canAddRow: canAddRow,
|
||||
};
|
||||
|
||||
if(CustomControl) {
|
||||
@ -246,7 +248,7 @@ export default function FormView({
|
||||
} else if(field.type === 'group') {
|
||||
groupLabels[field.id] = field.label;
|
||||
if(!visible) {
|
||||
schema.filterGroups.push(field.label);
|
||||
schemaRef.current.filterGroups.push(field.label);
|
||||
}
|
||||
} else {
|
||||
/* Its a form control */
|
||||
@ -330,6 +332,7 @@ export default function FormView({
|
||||
return <></>;
|
||||
}
|
||||
|
||||
let finalTabs = _.pickBy(tabs, (v, tabName)=>schemaRef.current.filterGroups.indexOf(tabName) <= -1);
|
||||
if(isTabView) {
|
||||
return (
|
||||
<>
|
||||
@ -345,16 +348,16 @@ export default function FormView({
|
||||
scrollButtons="auto"
|
||||
action={(ref)=>ref && ref.updateIndicator()}
|
||||
>
|
||||
{Object.keys(tabs).map((tabName)=>{
|
||||
{Object.keys(finalTabs).map((tabName)=>{
|
||||
return <Tab key={tabName} label={tabName} />;
|
||||
})}
|
||||
</Tabs>
|
||||
</Box>
|
||||
{Object.keys(tabs).map((tabName, i)=>{
|
||||
{Object.keys(finalTabs).map((tabName, i)=>{
|
||||
return (
|
||||
<TabPanel key={tabName} value={tabValue} index={i} classNameRoot={clsx(tabsClassname[tabName], isNested ? classes.nestedTabPanel : null)}
|
||||
className={fullTabs.indexOf(tabName) == -1 ? classes.nestedControl : null}>
|
||||
{tabs[tabName]}
|
||||
{finalTabs[tabName]}
|
||||
</TabPanel>
|
||||
);
|
||||
})}
|
||||
@ -364,9 +367,9 @@ export default function FormView({
|
||||
return (
|
||||
<>
|
||||
<Box height="100%" display="flex" flexDirection="column" className={className} ref={formRef}>
|
||||
{Object.keys(tabs).map((tabName)=>{
|
||||
{Object.keys(finalTabs).map((tabName)=>{
|
||||
return (
|
||||
<>{tabs[tabName]}</>
|
||||
<>{finalTabs[tabName]}</>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
|
@ -86,6 +86,11 @@ export default class BaseUISchema {
|
||||
});
|
||||
}
|
||||
|
||||
initialise() {
|
||||
/* Called when initial data loaded */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if current data is new or existing */
|
||||
isNew(state) {
|
||||
if(_.isUndefined(state)) {
|
||||
|
@ -30,12 +30,12 @@ import gettext from 'sources/gettext';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import FormView, { getFieldMetaData } from './FormView';
|
||||
import { pgAlertify } from '../helpers/legacyConnector';
|
||||
import { evalFunc } from 'sources/utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import CustomPropTypes from '../custom_prop_types';
|
||||
import { parseApiError } from '../api_instance';
|
||||
import DepListener, {DepListenerContext} from './DepListener';
|
||||
import FieldSetView from './FieldSetView';
|
||||
import DataGridView from './DataGridView';
|
||||
|
||||
const useDialogStyles = makeStyles((theme)=>({
|
||||
root: {
|
||||
@ -475,6 +475,7 @@ function SchemaDialogView({
|
||||
data = data || {};
|
||||
/* Set the origData to incoming data, useful for comparing and reset */
|
||||
schema.origData = prepareData(data || {});
|
||||
schema.initialise(data);
|
||||
sessDispatch({
|
||||
type: SCHEMA_STATE_ACTIONS.INIT,
|
||||
payload: schema.origData,
|
||||
@ -498,6 +499,15 @@ function SchemaDialogView({
|
||||
return ()=>clearTimeout(focusTimeout);
|
||||
}, []);
|
||||
|
||||
useEffect(()=>{
|
||||
/* If reset key changes, reset the form */
|
||||
sessDispatch({
|
||||
type: SCHEMA_STATE_ACTIONS.INIT,
|
||||
payload: schema.origData,
|
||||
});
|
||||
return true;
|
||||
}, [props.resetKey]);
|
||||
|
||||
const onResetClick = ()=>{
|
||||
const resetIt = ()=>{
|
||||
sessDispatch({
|
||||
@ -689,6 +699,7 @@ SchemaDialogView.propTypes = {
|
||||
disableSqlHelp: PropTypes.bool,
|
||||
disableDialogHelp: PropTypes.bool,
|
||||
showFooter: PropTypes.bool,
|
||||
resetKey: PropTypes.any,
|
||||
};
|
||||
|
||||
const usePropsStyles = makeStyles((theme)=>({
|
||||
@ -735,29 +746,13 @@ function SchemaPropertiesView({
|
||||
}, [getInitData]);
|
||||
|
||||
/* A simple loop to get all the controls for the fields */
|
||||
schema.fields.forEach((f)=>{
|
||||
let {visible, disabled, group, readonly, ...field} = f;
|
||||
schema.fields.forEach((field)=>{
|
||||
let {group} = field;
|
||||
let {visible, disabled, readonly, modeSupported} = getFieldMetaData(field, schema, origData, viewHelperProps);
|
||||
group = group || defaultTab;
|
||||
|
||||
let verInLimit = (_.isUndefined(viewHelperProps.serverInfo) ? true :
|
||||
((_.isUndefined(field.server_type) ? true :
|
||||
(viewHelperProps.serverInfo.type in field.server_type)) &&
|
||||
(_.isUndefined(field.min_version) ? true :
|
||||
(viewHelperProps.serverInfo.version >= field.min_version)) &&
|
||||
(_.isUndefined(field.max_version) ? true :
|
||||
(viewHelperProps.serverInfo.version <= field.max_version))));
|
||||
|
||||
let _visible = true;
|
||||
if(field.mode) {
|
||||
_visible = (field.mode.indexOf(viewHelperProps.mode) > -1);
|
||||
}
|
||||
if(_visible && visible) {
|
||||
_visible = evalFunc(schema, visible, origData);
|
||||
}
|
||||
|
||||
disabled = evalFunc(schema, disabled, origData);
|
||||
readonly = true;
|
||||
if(_visible && verInLimit) {
|
||||
if(visible && modeSupported) {
|
||||
if(!tabs[group]) tabs[group] = [];
|
||||
if(field && field.type === 'nested-fieldset') {
|
||||
tabs[group].push(
|
||||
@ -769,9 +764,27 @@ function SchemaPropertiesView({
|
||||
accessPath={[]}
|
||||
formErr={{}}
|
||||
controlClassName={classes.controlRow}
|
||||
visible={visible}
|
||||
{...field} />
|
||||
);
|
||||
}else{
|
||||
} else if(field.type === 'collection') {
|
||||
tabs[group].push(
|
||||
<DataGridView
|
||||
key={field.id}
|
||||
viewHelperProps={viewHelperProps}
|
||||
name={field.id}
|
||||
value={origData[field.id]}
|
||||
schema={field.schema}
|
||||
accessPath={[field.id]}
|
||||
formErr={{}}
|
||||
controlClassName={classes.controlRow}
|
||||
canAdd={false}
|
||||
canEdit={false}
|
||||
canDelete={false}
|
||||
visible={visible}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
tabs[group].push(
|
||||
<MappedFormControl
|
||||
key={field.id}
|
||||
@ -781,7 +794,7 @@ function SchemaPropertiesView({
|
||||
value={origData[field.id]}
|
||||
readonly={readonly}
|
||||
disabled={disabled}
|
||||
visible={_visible}
|
||||
visible={visible}
|
||||
{...field}
|
||||
className={classes.controlRow}
|
||||
/>
|
||||
|
@ -6,6 +6,7 @@ import { DefaultButton } from '../components/Buttons';
|
||||
import { evalFunc } from '../utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import CustomPropTypes from '../custom_prop_types';
|
||||
import _ from 'lodash';
|
||||
|
||||
const useStyles = makeStyles((theme)=>({
|
||||
formBorder: {
|
||||
@ -26,14 +27,10 @@ export default function DataGridViewWithHeaderForm(props) {
|
||||
const headerFormData = useRef({});
|
||||
const schemaRef = useRef(otherProps.schema);
|
||||
const [isAddDisabled, setAddDisabled] = useState(true);
|
||||
|
||||
const [headerFormResetKey, setHeaderFormResetKey] = useState(0);
|
||||
const onAddClick = useCallback(()=>{
|
||||
if(otherProps.canAddRow) {
|
||||
let state = schemaRef.current.top ? schemaRef.current.top.sessData : schemaRef.current.sessData;
|
||||
let canAddRow = evalFunc(schemaRef.current, otherProps.canAddRow, state || {});
|
||||
if(!canAddRow) {
|
||||
return;
|
||||
}
|
||||
if(!otherProps.canAddRow) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newRow = headerSchema.getNewData(headerFormData.current);
|
||||
@ -42,13 +39,16 @@ export default function DataGridViewWithHeaderForm(props) {
|
||||
path: otherProps.accessPath,
|
||||
value: newRow,
|
||||
});
|
||||
setHeaderFormResetKey((preVal)=>preVal+1);
|
||||
}, []);
|
||||
|
||||
useEffect(()=>{
|
||||
headerSchema.top = schemaRef.current.top;
|
||||
}, []);
|
||||
|
||||
let state = schemaRef.current.top ? schemaRef.current.top.origData : schemaRef.current.origData;
|
||||
let state = schemaRef.current.top ? _.get(schemaRef.current.top.sessData, _.slice(otherProps.accessPath, 0, -1))
|
||||
: _.get(schemaRef.current.sessData);
|
||||
|
||||
headerVisible = headerVisible && evalFunc(null, headerVisible, state);
|
||||
return (
|
||||
<Box className={containerClassName}>
|
||||
@ -67,6 +67,7 @@ export default function DataGridViewWithHeaderForm(props) {
|
||||
}}
|
||||
hasSQL={false}
|
||||
isTabView={false}
|
||||
resetKey={headerFormResetKey}
|
||||
/>
|
||||
<Box display="flex">
|
||||
<DefaultButton className={classes.addBtn} onClick={onAddClick} disabled={isAddDisabled}>Add</DefaultButton>
|
||||
|
Loading…
Reference in New Issue
Block a user