Allow two controls to be inline in SchemaView.
parent
7686280cb2
commit
a08714cd65
|
@ -18,6 +18,7 @@ import CustomPropTypes from '../custom_prop_types';
|
||||||
import { DepListenerContext } from './DepListener';
|
import { DepListenerContext } from './DepListener';
|
||||||
import { getFieldMetaData } from './FormView';
|
import { getFieldMetaData } from './FormView';
|
||||||
import FieldSet from '../components/FieldSet';
|
import FieldSet from '../components/FieldSet';
|
||||||
|
import { Box } from '@material-ui/core';
|
||||||
|
|
||||||
export default function FieldSetView({
|
export default function FieldSetView({
|
||||||
value, schema={}, viewHelperProps, accessPath, dataDispatch, controlClassName, isDataGridForm=false, label, visible}) {
|
value, schema={}, viewHelperProps, accessPath, dataDispatch, controlClassName, isDataGridForm=false, label, visible}) {
|
||||||
|
@ -46,6 +47,8 @@ export default function FieldSetView({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
let viewFields = [];
|
let viewFields = [];
|
||||||
|
let inlineComponents = [];
|
||||||
|
|
||||||
/* Prepare the array of components based on the types */
|
/* Prepare the array of components based on the types */
|
||||||
for(const field of schema.fields) {
|
for(const field of schema.fields) {
|
||||||
let {visible, disabled, readonly, modeSupported} =
|
let {visible, disabled, readonly, modeSupported} =
|
||||||
|
@ -58,40 +61,63 @@ export default function FieldSetView({
|
||||||
* lets pass the new changes to dependent and get the new values
|
* lets pass the new changes to dependent and get the new values
|
||||||
* from there as well.
|
* from there as well.
|
||||||
*/
|
*/
|
||||||
viewFields.push(
|
const currentControl = <MappedFormControl
|
||||||
<MappedFormControl
|
state={value}
|
||||||
state={value}
|
key={field.id}
|
||||||
key={field.id}
|
viewHelperProps={viewHelperProps}
|
||||||
viewHelperProps={viewHelperProps}
|
name={field.id}
|
||||||
name={field.id}
|
value={value[field.id]}
|
||||||
value={value[field.id]}
|
{...field}
|
||||||
{...field}
|
readonly={readonly}
|
||||||
readonly={readonly}
|
disabled={disabled}
|
||||||
disabled={disabled}
|
visible={visible}
|
||||||
visible={visible}
|
onChange={(changeValue)=>{
|
||||||
onChange={(changeValue)=>{
|
/* Get the changes on dependent fields as well */
|
||||||
/* Get the changes on dependent fields as well */
|
dataDispatch({
|
||||||
dataDispatch({
|
type: SCHEMA_STATE_ACTIONS.SET_VALUE,
|
||||||
type: SCHEMA_STATE_ACTIONS.SET_VALUE,
|
path: accessPath.concat(field.id),
|
||||||
path: accessPath.concat(field.id),
|
value: changeValue,
|
||||||
value: changeValue,
|
});
|
||||||
});
|
}}
|
||||||
}}
|
hasError={hasError}
|
||||||
hasError={hasError}
|
className={controlClassName}
|
||||||
className={controlClassName}
|
memoDeps={[
|
||||||
memoDeps={[
|
value[field.id],
|
||||||
value[field.id],
|
readonly,
|
||||||
readonly,
|
disabled,
|
||||||
disabled,
|
visible,
|
||||||
visible,
|
hasError,
|
||||||
hasError,
|
controlClassName,
|
||||||
controlClassName,
|
...(evalFunc(null, field.deps) || []).map((dep)=>value[dep]),
|
||||||
...(evalFunc(null, field.deps) || []).map((dep)=>value[dep]),
|
]}
|
||||||
]}
|
/>;
|
||||||
/>
|
|
||||||
);
|
if(field.inlineNext) {
|
||||||
|
inlineComponents.push(React.cloneElement(currentControl, {
|
||||||
|
withContainer: false, controlGridBasis: 3
|
||||||
|
}));
|
||||||
|
} else if(inlineComponents?.length > 0) {
|
||||||
|
inlineComponents.push(React.cloneElement(currentControl, {
|
||||||
|
withContainer: false, controlGridBasis: 3
|
||||||
|
}));
|
||||||
|
viewFields.push(
|
||||||
|
<Box key={`ic-${inlineComponents[0].key}`} display="flex" className={controlClassName} gridRowGap="8px" flexWrap="wrap">
|
||||||
|
{inlineComponents}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
inlineComponents = [];
|
||||||
|
} else {
|
||||||
|
viewFields.push(currentControl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(inlineComponents?.length > 0) {
|
||||||
|
viewFields.push(
|
||||||
|
<Box key={`ic-${inlineComponents[0].key}`} display="flex" className={controlClassName} gridRowGap="8px" flexWrap="wrap">
|
||||||
|
{inlineComponents}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if(!visible) {
|
if(!visible) {
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|
|
@ -212,6 +212,8 @@ export default function FormView({
|
||||||
}, [stateUtils.formResetKey]);
|
}, [stateUtils.formResetKey]);
|
||||||
|
|
||||||
let fullTabs = [];
|
let fullTabs = [];
|
||||||
|
let inlineComponents = [];
|
||||||
|
let inlineCompGroup = null;
|
||||||
|
|
||||||
/* Prepare the array of components based on the types */
|
/* Prepare the array of components based on the types */
|
||||||
for(const field of schemaRef.current.fields) {
|
for(const field of schemaRef.current.fields) {
|
||||||
|
@ -304,49 +306,75 @@ export default function FormView({
|
||||||
firstEleID.current = field.id;
|
firstEleID.current = field.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs[group].push(
|
const currentControl = <MappedFormControl
|
||||||
<MappedFormControl
|
inputRef={(ele)=>{
|
||||||
inputRef={(ele)=>{
|
if(firstEleRef && firstEleID.current === field.id) {
|
||||||
if(firstEleRef && firstEleID.current === field.id) {
|
firstEleRef.current = ele;
|
||||||
firstEleRef.current = ele;
|
}
|
||||||
}
|
}}
|
||||||
}}
|
state={value}
|
||||||
state={value}
|
key={id}
|
||||||
key={id}
|
viewHelperProps={viewHelperProps}
|
||||||
viewHelperProps={viewHelperProps}
|
name={id}
|
||||||
name={id}
|
value={value[id]}
|
||||||
value={value[id]}
|
{...field}
|
||||||
{...field}
|
id={id}
|
||||||
id={id}
|
readonly={readonly}
|
||||||
readonly={readonly}
|
disabled={disabled}
|
||||||
disabled={disabled}
|
visible={visible}
|
||||||
visible={visible}
|
onChange={(changeValue)=>{
|
||||||
onChange={(changeValue)=>{
|
/* Get the changes on dependent fields as well */
|
||||||
/* Get the changes on dependent fields as well */
|
dataDispatch({
|
||||||
dataDispatch({
|
type: SCHEMA_STATE_ACTIONS.SET_VALUE,
|
||||||
type: SCHEMA_STATE_ACTIONS.SET_VALUE,
|
path: accessPath.concat(id),
|
||||||
path: accessPath.concat(id),
|
value: changeValue,
|
||||||
value: changeValue,
|
});
|
||||||
});
|
}}
|
||||||
}}
|
hasError={hasError}
|
||||||
hasError={hasError}
|
className={classes.controlRow}
|
||||||
className={classes.controlRow}
|
noLabel={field.isFullTab}
|
||||||
noLabel={field.isFullTab}
|
memoDeps={[
|
||||||
memoDeps={[
|
value[id],
|
||||||
value[id],
|
readonly,
|
||||||
readonly,
|
disabled,
|
||||||
disabled,
|
visible,
|
||||||
visible,
|
hasError,
|
||||||
hasError,
|
classes.controlRow,
|
||||||
classes.controlRow,
|
...(evalFunc(null, field.deps) || []).map((dep)=>value[dep]),
|
||||||
...(evalFunc(null, field.deps) || []).map((dep)=>value[dep]),
|
]}
|
||||||
]}
|
/>;
|
||||||
/>
|
|
||||||
);
|
if(field.inlineNext) {
|
||||||
|
inlineComponents.push(React.cloneElement(currentControl, {
|
||||||
|
withContainer: false, controlGridBasis: 3
|
||||||
|
}));
|
||||||
|
inlineCompGroup = group;
|
||||||
|
} else if(inlineComponents?.length > 0) {
|
||||||
|
inlineComponents.push(React.cloneElement(currentControl, {
|
||||||
|
withContainer: false, controlGridBasis: 3
|
||||||
|
}));
|
||||||
|
tabs[group].push(
|
||||||
|
<Box key={`ic-${inlineComponents[0].key}`} display="flex" className={classes.controlRow} gridRowGap="8px" flexWrap="wrap">
|
||||||
|
{inlineComponents}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
inlineComponents = [];
|
||||||
|
inlineCompGroup = null;
|
||||||
|
} else {
|
||||||
|
tabs[group].push(currentControl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(inlineComponents?.length > 0) {
|
||||||
|
tabs[inlineCompGroup].push(
|
||||||
|
<Box key={`ic-${inlineComponents[0].key}`} display="flex" className={classes.controlRow} gridRowGap="8px" flexWrap="wrap">
|
||||||
|
{inlineComponents}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let finalTabs = _.pickBy(tabs, (v, tabName)=>schemaRef.current.filterGroups.indexOf(tabName) <= -1);
|
let finalTabs = _.pickBy(tabs, (v, tabName)=>schemaRef.current.filterGroups.indexOf(tabName) <= -1);
|
||||||
|
|
||||||
/* Add the SQL tab if required */
|
/* Add the SQL tab if required */
|
||||||
|
|
|
@ -201,7 +201,8 @@ const ALLOWED_PROPS_FIELD_COMMON = [
|
||||||
'mode', 'value', 'readonly', 'disabled', 'hasError', 'id',
|
'mode', 'value', 'readonly', 'disabled', 'hasError', 'id',
|
||||||
'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
|
'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
|
||||||
'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
|
'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
|
||||||
'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName', 'hidden'
|
'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName', 'hidden',
|
||||||
|
'withContainer', 'controlGridBasis',
|
||||||
];
|
];
|
||||||
|
|
||||||
const ALLOWED_PROPS_FIELD_FORM = [
|
const ALLOWED_PROPS_FIELD_FORM = [
|
||||||
|
|
|
@ -125,19 +125,37 @@ FormIcon.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Wrapper on any form component to add label, error indicator and help message */
|
/* Wrapper on any form component to add label, error indicator and help message */
|
||||||
export function FormInput({ children, error, className, label, helpMessage, required, testcid }) {
|
export function FormInput({ children, error, className, label, helpMessage, required, testcid, withContainer=true, labelGridBasis=3, controlGridBasis=9 }) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const cid = testcid || _.uniqueId('c');
|
const cid = testcid || _.uniqueId('c');
|
||||||
const helpid = `h${cid}`;
|
const helpid = `h${cid}`;
|
||||||
|
if(!withContainer) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Grid item lg={labelGridBasis} md={labelGridBasis} sm={12} xs={12}>
|
||||||
|
<InputLabel htmlFor={cid} className={clsx(classes.formLabel, error ? classes.formLabelError : null)} required={required}>
|
||||||
|
{label}
|
||||||
|
<FormIcon type={MESSAGE_TYPE.ERROR} style={{ marginLeft: 'auto', visibility: error ? 'unset' : 'hidden' }} />
|
||||||
|
</InputLabel>
|
||||||
|
</Grid>
|
||||||
|
<Grid item lg={controlGridBasis} md={controlGridBasis} sm={12} xs={12}>
|
||||||
|
<FormControl error={Boolean(error)} fullWidth>
|
||||||
|
{React.cloneElement(children, { cid, helpid })}
|
||||||
|
</FormControl>
|
||||||
|
<FormHelperText id={helpid} variant="outlined">{HTMLReactParse(helpMessage || '')}</FormHelperText>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={0} className={className}>
|
<Grid container spacing={0} className={className}>
|
||||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
<Grid item lg={labelGridBasis} md={labelGridBasis} sm={12} xs={12}>
|
||||||
<InputLabel htmlFor={cid} className={clsx(classes.formLabel, error ? classes.formLabelError : null)} required={required}>
|
<InputLabel htmlFor={cid} className={clsx(classes.formLabel, error ? classes.formLabelError : null)} required={required}>
|
||||||
{label}
|
{label}
|
||||||
<FormIcon type={MESSAGE_TYPE.ERROR} style={{ marginLeft: 'auto', visibility: error ? 'unset' : 'hidden' }} />
|
<FormIcon type={MESSAGE_TYPE.ERROR} style={{ marginLeft: 'auto', visibility: error ? 'unset' : 'hidden' }} />
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
<Grid item lg={controlGridBasis} md={controlGridBasis} sm={12} xs={12}>
|
||||||
<FormControl error={Boolean(error)} fullWidth>
|
<FormControl error={Boolean(error)} fullWidth>
|
||||||
{React.cloneElement(children, { cid, helpid })}
|
{React.cloneElement(children, { cid, helpid })}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -154,6 +172,9 @@ FormInput.propTypes = {
|
||||||
helpMessage: PropTypes.string,
|
helpMessage: PropTypes.string,
|
||||||
required: PropTypes.bool,
|
required: PropTypes.bool,
|
||||||
testcid: PropTypes.any,
|
testcid: PropTypes.any,
|
||||||
|
withContainer: PropTypes.bool,
|
||||||
|
labelGridBasis: PropTypes.number,
|
||||||
|
controlGridBasis: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function InputSQL({ value, options, onChange, className, controlProps, inputRef, ...props }) {
|
export function InputSQL({ value, options, onChange, className, controlProps, inputRef, ...props }) {
|
||||||
|
@ -512,10 +533,10 @@ InputSwitch.propTypes = {
|
||||||
controlProps: PropTypes.object,
|
controlProps: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, ...props }) {
|
export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, withContainer, controlGridBasis, ...props }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}>
|
<FormInput required={required} label={label} error={hasError} className={className}
|
||||||
|
helpMessage={helpMessage} testcid={testcid} withContainer={withContainer} controlGridBasis={controlGridBasis}>
|
||||||
<InputSwitch {...props} />
|
<InputSwitch {...props} />
|
||||||
</FormInput>
|
</FormInput>
|
||||||
);
|
);
|
||||||
|
@ -527,6 +548,8 @@ FormInputSwitch.propTypes = {
|
||||||
className: CustomPropTypes.className,
|
className: CustomPropTypes.className,
|
||||||
helpMessage: PropTypes.string,
|
helpMessage: PropTypes.string,
|
||||||
testcid: PropTypes.string,
|
testcid: PropTypes.string,
|
||||||
|
withContainer: PropTypes.bool,
|
||||||
|
controlGridBasis: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function InputCheckbox({ cid, helpid, value, onChange, controlProps, readonly, ...props }) {
|
export function InputCheckbox({ cid, helpid, value, onChange, controlProps, readonly, ...props }) {
|
||||||
|
@ -1019,10 +1042,11 @@ InputColor.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FormInputColor({
|
export function FormInputColor({
|
||||||
hasError, required, className, label, helpMessage, testcid, ...props }) {
|
hasError, required, className, label, helpMessage, testcid, withContainer, controlGridBasis, ...props }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}>
|
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}
|
||||||
|
withContainer={withContainer} controlGridBasis={controlGridBasis}>
|
||||||
<InputColor {...props} />
|
<InputColor {...props} />
|
||||||
</FormInput>
|
</FormInput>
|
||||||
);
|
);
|
||||||
|
@ -1034,6 +1058,8 @@ FormInputColor.propTypes = {
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
helpMessage: PropTypes.string,
|
helpMessage: PropTypes.string,
|
||||||
testcid: PropTypes.string,
|
testcid: PropTypes.string,
|
||||||
|
withContainer: PropTypes.bool,
|
||||||
|
controlGridBasis: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function PlainString({ controlProps, value }) {
|
export function PlainString({ controlProps, value }) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ export class SectionSchema extends BaseUISchema {
|
||||||
state.only_tablespaces ||
|
state.only_tablespaces ||
|
||||||
state.only_roles;
|
state.only_roles;
|
||||||
},
|
},
|
||||||
|
inlineNext: true,
|
||||||
}, {
|
}, {
|
||||||
id: 'data',
|
id: 'data',
|
||||||
label: gettext('Data'),
|
label: gettext('Data'),
|
||||||
|
|
Loading…
Reference in New Issue