mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
CE-1115 - support having the ReportSetupWidget and PivotTableSetupWidget actually edit the form values used on the page
This commit is contained in:
@ -43,7 +43,9 @@ import DynamicFormUtils from "qqq/components/forms/DynamicFormUtils";
|
|||||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||||
import HelpContent from "qqq/components/misc/HelpContent";
|
import HelpContent from "qqq/components/misc/HelpContent";
|
||||||
import QRecordSidebar from "qqq/components/misc/RecordSidebar";
|
import QRecordSidebar from "qqq/components/misc/RecordSidebar";
|
||||||
|
import PivotTableSetupWidget from "qqq/components/widgets/misc/PivotTableSetupWidget";
|
||||||
import RecordGridWidget, {ChildRecordListData} from "qqq/components/widgets/misc/RecordGridWidget";
|
import RecordGridWidget, {ChildRecordListData} from "qqq/components/widgets/misc/RecordGridWidget";
|
||||||
|
import ReportSetupWidget from "qqq/components/widgets/misc/ReportSetupWidget";
|
||||||
import HtmlUtils from "qqq/utils/HtmlUtils";
|
import HtmlUtils from "qqq/utils/HtmlUtils";
|
||||||
import Client from "qqq/utils/qqq/Client";
|
import Client from "qqq/utils/qqq/Client";
|
||||||
import TableUtils from "qqq/utils/qqq/TableUtils";
|
import TableUtils from "qqq/utils/qqq/TableUtils";
|
||||||
@ -77,6 +79,15 @@ EntityForm.defaultProps = {
|
|||||||
onSubmitCallback: null,
|
onSubmitCallback: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define a function that we can make referenes to, which we'll overwrite //
|
||||||
|
// with formik's setFieldValue function, once we're inside formik. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: boolean): void =>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
function EntityForm(props: Props): JSX.Element
|
function EntityForm(props: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
@ -108,6 +119,9 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
|
|
||||||
const [notAllowedError, setNotAllowedError] = useState(null as string);
|
const [notAllowedError, setNotAllowedError] = useState(null as string);
|
||||||
|
|
||||||
|
const [recordValuesJSON, setRecordValuesJSON] = useState("");
|
||||||
|
const [formValues, setFormValues] = useState({} as {[name: string]: any});
|
||||||
|
|
||||||
const {pageHeader, setPageHeader} = useContext(QContext);
|
const {pageHeader, setPageHeader} = useContext(QContext);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -269,6 +283,21 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Watch the record values - if they change, re-render widgets
|
||||||
|
*******************************************************************************/
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const newRenderedWidgetSections: {[name: string]: JSX.Element} = {};
|
||||||
|
for (let widgetName in renderedWidgetSections)
|
||||||
|
{
|
||||||
|
const widgetMetaData = metaData.widgets.get(widgetName);
|
||||||
|
newRenderedWidgetSections[widgetName] = getWidgetSection(widgetMetaData, childListWidgetData[widgetName]);
|
||||||
|
}
|
||||||
|
setRenderedWidgetSections(newRenderedWidgetSections);
|
||||||
|
}, [recordValuesJSON]);
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** render a section (full of fields) as a form
|
** render a section (full of fields) as a form
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -319,25 +348,66 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** if we have a widget that wants to set form-field values, they can take this
|
||||||
|
** function in as a callback, and then call it with their values.
|
||||||
|
*******************************************************************************/
|
||||||
|
function setFormFieldValuesFromWidget(values: {[name: string]: any})
|
||||||
|
{
|
||||||
|
for (let key in values)
|
||||||
|
{
|
||||||
|
formikSetFieldValueFunction(key, values[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** render a section as a widget
|
** render a section as a widget
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
function getWidgetSection(widgetMetaData: QWidgetMetaData, widgetData: any): JSX.Element
|
function getWidgetSection(widgetMetaData: QWidgetMetaData, widgetData: any): JSX.Element
|
||||||
{
|
{
|
||||||
widgetData.viewAllLink = null;
|
if(widgetMetaData.type == "childRecordList")
|
||||||
widgetMetaData.showExportButton = false;
|
{
|
||||||
|
widgetData.viewAllLink = null;
|
||||||
|
widgetMetaData.showExportButton = false;
|
||||||
|
|
||||||
return <RecordGridWidget
|
return <RecordGridWidget
|
||||||
key={new Date().getTime()} // added so that editing values actually re-renders...
|
key={new Date().getTime()} // added so that editing values actually re-renders...
|
||||||
widgetMetaData={widgetMetaData}
|
widgetMetaData={widgetMetaData}
|
||||||
data={widgetData}
|
data={widgetData}
|
||||||
disableRowClick
|
disableRowClick
|
||||||
allowRecordEdit
|
allowRecordEdit
|
||||||
allowRecordDelete
|
allowRecordDelete
|
||||||
addNewRecordCallback={() => openAddChildRecord(widgetMetaData.name, widgetData)}
|
addNewRecordCallback={() => openAddChildRecord(widgetMetaData.name, widgetData)}
|
||||||
editRecordCallback={(rowIndex) => openEditChildRecord(widgetMetaData.name, widgetData, rowIndex)}
|
editRecordCallback={(rowIndex) => openEditChildRecord(widgetMetaData.name, widgetData, rowIndex)}
|
||||||
deleteRecordCallback={(rowIndex) => deleteChildRecord(widgetMetaData.name, widgetData, rowIndex)}
|
deleteRecordCallback={(rowIndex) => deleteChildRecord(widgetMetaData.name, widgetData, rowIndex)}
|
||||||
/>;
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widgetMetaData.type == "reportSetup")
|
||||||
|
{
|
||||||
|
return <ReportSetupWidget
|
||||||
|
key={formValues["tableName"]} // todo, is this good? it was added so that editing values actually re-renders...
|
||||||
|
isEditable={true}
|
||||||
|
widgetMetaData={widgetMetaData}
|
||||||
|
recordValues={formValues}
|
||||||
|
onSaveCallback={setFormFieldValuesFromWidget}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widgetMetaData.type == "pivotTableSetup")
|
||||||
|
{
|
||||||
|
return <PivotTableSetupWidget
|
||||||
|
key={formValues["tableName"]} // todo, is this good? it was added so that editing values actually re-renders...
|
||||||
|
isEditable={true}
|
||||||
|
widgetMetaData={widgetMetaData}
|
||||||
|
recordValues={formValues}
|
||||||
|
onSaveCallback={setFormFieldValuesFromWidget}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<Box>Unsupported widget type: {widgetMetaData.type}</Box>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -373,7 +443,21 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
const tableSections = TableUtils.getSectionsForRecordSidebar(tableMetaData, [...tableMetaData.fields.keys()], (section: QTableSection) =>
|
const tableSections = TableUtils.getSectionsForRecordSidebar(tableMetaData, [...tableMetaData.fields.keys()], (section: QTableSection) =>
|
||||||
{
|
{
|
||||||
return section.widgetName && metaData.widgets.get(section.widgetName)?.type == "childRecordList" && metaData.widgets.get(section.widgetName)?.defaultValues?.has("manageAssociationName");
|
const widget = metaData.widgets.get(section.widgetName);
|
||||||
|
if(widget)
|
||||||
|
{
|
||||||
|
if(widget.type == "childRecordList" && widget.defaultValues?.has("manageAssociationName"))
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widget.type == "reportSetup" || widget.type == "pivotTableSetup")
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
});
|
});
|
||||||
setTableSections(tableSections);
|
setTableSections(tableSections);
|
||||||
|
|
||||||
@ -549,13 +633,7 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasFields = section.fieldNames && section.fieldNames.length > 0;
|
const hasFields = section.fieldNames && section.fieldNames.length > 0;
|
||||||
const hasChildRecordListWidget = section.widgetName && metaData.widgets.get(section.widgetName)?.type == "childRecordList";
|
if(hasFields)
|
||||||
if (!hasFields && !hasChildRecordListWidget)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasFields)
|
|
||||||
{
|
{
|
||||||
for (let j = 0; j < section.fieldNames.length; j++)
|
for (let j = 0; j < section.fieldNames.length; j++)
|
||||||
{
|
{
|
||||||
@ -599,6 +677,7 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
newRenderedWidgetSections[section.widgetName] = getWidgetSection(widgetMetaData, widgetData);
|
newRenderedWidgetSections[section.widgetName] = getWidgetSection(widgetMetaData, widgetData);
|
||||||
newChildListWidgetData[section.widgetName] = widgetData;
|
newChildListWidgetData[section.widgetName] = widgetData;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// capture the tier1 section's name //
|
// capture the tier1 section's name //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -924,51 +1003,71 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
errors,
|
errors,
|
||||||
touched,
|
touched,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
}) => (
|
setFieldValue,
|
||||||
<Form id={formId} autoComplete="off">
|
}) =>
|
||||||
<ScrollToFirstError />
|
{
|
||||||
|
if(values)
|
||||||
|
{
|
||||||
|
const newRecordValuesJSON = JSON.stringify(values);
|
||||||
|
if(recordValuesJSON != newRecordValuesJSON)
|
||||||
|
{
|
||||||
|
setRecordValuesJSON(newRecordValuesJSON);
|
||||||
|
setFormValues(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<Box pb={3} pt={0}>
|
///////////////////////////////////////////////////////////////////
|
||||||
<Card id={`${t1sectionName}`} sx={{overflow: "visible", pb: 2, scrollMarginTop: "100px"}} elevation={cardElevation}>
|
// once we're in the formik form, use its setFieldValue function //
|
||||||
<Box display="flex" p={3} pb={1}>
|
// over top of the default one we created globally //
|
||||||
<Box mr={1.5}>
|
///////////////////////////////////////////////////////////////////
|
||||||
<Avatar sx={{bgcolor: accentColor}}>
|
formikSetFieldValueFunction = setFieldValue;
|
||||||
<Icon>
|
|
||||||
{tableMetaData?.iconName}
|
return (
|
||||||
</Icon>
|
<Form id={formId} autoComplete="off">
|
||||||
</Avatar>
|
<ScrollToFirstError />
|
||||||
</Box>
|
|
||||||
<Box display="flex" alignItems="center">
|
<Box pb={3} pt={0}>
|
||||||
<MDTypography variant="h5">{formTitle}</MDTypography>
|
<Card id={`${t1sectionName}`} sx={{overflow: "visible", pb: 2, scrollMarginTop: "100px"}} elevation={cardElevation}>
|
||||||
</Box>
|
<Box display="flex" p={3} pb={1}>
|
||||||
</Box>
|
<Box mr={1.5}>
|
||||||
{t1section && getSectionHelp(t1section)}
|
<Avatar sx={{bgcolor: accentColor}}>
|
||||||
{
|
<Icon>
|
||||||
t1sectionName && formFields ? (
|
{tableMetaData?.iconName}
|
||||||
<Box px={3}>
|
</Icon>
|
||||||
<Box pb={"0.25rem"} width="100%">
|
</Avatar>
|
||||||
{getFormSection(t1section, values, touched, formFields.get(t1sectionName), errors, true)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
) : null
|
<Box display="flex" alignItems="center">
|
||||||
}
|
<MDTypography variant="h5">{formTitle}</MDTypography>
|
||||||
</Card>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{formFields && nonT1Sections.length ? nonT1Sections.map((section: QTableSection) => (
|
{t1section && getSectionHelp(t1section)}
|
||||||
<Box key={`edit-card-${section.name}`} pb={3}>
|
{
|
||||||
{renderSection(section, values, touched, formFields, errors)}
|
t1sectionName && formFields ? (
|
||||||
|
<Box px={3}>
|
||||||
|
<Box pb={"0.25rem"} width="100%">
|
||||||
|
{getFormSection(t1section, values, touched, formFields.get(t1sectionName), errors, true)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
)) : null}
|
{formFields && nonT1Sections.length ? nonT1Sections.map((section: QTableSection) => (
|
||||||
|
<Box key={`edit-card-${section.name}`} pb={3}>
|
||||||
|
{renderSection(section, values, touched, formFields, errors)}
|
||||||
|
</Box>
|
||||||
|
)) : null}
|
||||||
|
|
||||||
<Box component="div" p={3}>
|
<Box component="div" p={3}>
|
||||||
<Grid container justifyContent="flex-end" spacing={3}>
|
<Grid container justifyContent="flex-end" spacing={3}>
|
||||||
<QCancelButton onClickHandler={props.isModal ? props.closeModalHandler : handleCancelClicked} disabled={isSubmitting} />
|
<QCancelButton onClickHandler={props.isModal ? props.closeModalHandler : handleCancelClicked} disabled={isSubmitting} />
|
||||||
<QSaveButton disabled={isSubmitting} />
|
<QSaveButton disabled={isSubmitting} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
);
|
||||||
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user