mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 13:20:43 +00:00
CE-1727 - Add support for ad-hoc, composite/block widgets; support processFlow (e.g., non-linear); some mobile-style adjustments
This commit is contained in:
@ -29,6 +29,7 @@ import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstan
|
|||||||
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
||||||
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobComplete";
|
import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobComplete";
|
||||||
import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError";
|
import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError";
|
||||||
import {QJobRunning} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobRunning";
|
import {QJobRunning} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobRunning";
|
||||||
@ -36,12 +37,14 @@ import {QJobStarted} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJob
|
|||||||
import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
|
import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
|
||||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||||
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
|
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
|
||||||
import {Alert, Box, Button, CircularProgress, Icon, TablePagination} from "@mui/material";
|
import {Alert, Button, CircularProgress, Icon, TablePagination} from "@mui/material";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
import Card from "@mui/material/Card";
|
import Card from "@mui/material/Card";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import Step from "@mui/material/Step";
|
import Step from "@mui/material/Step";
|
||||||
import StepLabel from "@mui/material/StepLabel";
|
import StepLabel from "@mui/material/StepLabel";
|
||||||
import Stepper from "@mui/material/Stepper";
|
import Stepper from "@mui/material/Stepper";
|
||||||
|
import {Theme} from "@mui/material/styles";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import {DataGridPro, GridColDef} from "@mui/x-data-grid-pro";
|
import {DataGridPro, GridColDef} from "@mui/x-data-grid-pro";
|
||||||
import FormData from "form-data";
|
import FormData from "form-data";
|
||||||
@ -60,8 +63,11 @@ import QRecordSidebar from "qqq/components/misc/RecordSidebar";
|
|||||||
import {GoogleDriveFolderPickerWrapper} from "qqq/components/processes/GoogleDriveFolderPickerWrapper";
|
import {GoogleDriveFolderPickerWrapper} from "qqq/components/processes/GoogleDriveFolderPickerWrapper";
|
||||||
import ProcessSummaryResults from "qqq/components/processes/ProcessSummaryResults";
|
import ProcessSummaryResults from "qqq/components/processes/ProcessSummaryResults";
|
||||||
import ValidationReview from "qqq/components/processes/ValidationReview";
|
import ValidationReview from "qqq/components/processes/ValidationReview";
|
||||||
|
import {BlockData} from "qqq/components/widgets/blocks/BlockModels";
|
||||||
|
import CompositeWidget, {CompositeData} from "qqq/components/widgets/CompositeWidget";
|
||||||
import DashboardWidgets from "qqq/components/widgets/DashboardWidgets";
|
import DashboardWidgets from "qqq/components/widgets/DashboardWidgets";
|
||||||
import BaseLayout from "qqq/layouts/BaseLayout";
|
import BaseLayout from "qqq/layouts/BaseLayout";
|
||||||
|
import ProcessWidgetBlockUtils from "qqq/pages/processes/ProcessWidgetBlockUtils";
|
||||||
import {TABLE_VARIANT_LOCAL_STORAGE_KEY_ROOT} from "qqq/pages/records/query/RecordQuery";
|
import {TABLE_VARIANT_LOCAL_STORAGE_KEY_ROOT} from "qqq/pages/records/query/RecordQuery";
|
||||||
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";
|
||||||
@ -89,14 +95,18 @@ const INITIAL_RETRY_MILLIS = 1_500;
|
|||||||
const RETRY_MAX_MILLIS = 12_000;
|
const RETRY_MAX_MILLIS = 12_000;
|
||||||
const BACKOFF_AMOUNT = 1.5;
|
const BACKOFF_AMOUNT = 1.5;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// define a function that we can make referenes to, which we'll overwrite //
|
// define some functions that we can make referene to, which we'll overwrite //
|
||||||
// with formik's setFieldValue function, once we're inside formik. //
|
// with functions from formik, once we're inside formik. //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: boolean): void =>
|
let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: boolean): void =>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let formikSetTouched = ({}: any, touched: boolean): void =>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
const cachedPossibleValueLabels: { [fieldName: string]: { [id: string | number]: string } } = {};
|
const cachedPossibleValueLabels: { [fieldName: string]: { [id: string | number]: string } } = {};
|
||||||
|
|
||||||
function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, isReport, recordIds, closeModalHandler, forceReInit, overrideLabel}: Props): JSX.Element
|
function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, isReport, recordIds, closeModalHandler, forceReInit, overrideLabel}: Props): JSX.Element
|
||||||
@ -157,8 +167,30 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const [overrideOnLastStep, setOverrideOnLastStep] = useState(null as boolean);
|
const [overrideOnLastStep, setOverrideOnLastStep] = useState(null as boolean);
|
||||||
|
|
||||||
const onLastStep = activeStepIndex === steps.length - 2;
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
const noMoreSteps = activeStepIndex === steps.length - 1;
|
// determine if we're on the last-step or not (e.g., to decide "Submit" vs "Next"( //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
let onLastStep = false;
|
||||||
|
if (processMetaData?.stepFlow == "LINEAR" && activeStepIndex === steps.length - 2)
|
||||||
|
{
|
||||||
|
onLastStep = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// determine if any 'next' button appears //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
let noMoreSteps = false;
|
||||||
|
if (processMetaData?.stepFlow == "LINEAR" && activeStepIndex === steps.length - 1)
|
||||||
|
{
|
||||||
|
noMoreSteps = true;
|
||||||
|
}
|
||||||
|
if(processValues["noMoreSteps"])
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// this, to allow a non-linear process to request this behavior //
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
noMoreSteps = true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// form state //
|
// form state //
|
||||||
@ -326,6 +358,69 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
return renderedWidget;
|
return renderedWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
** callback used by widget blocks, e.g., for input-text-enter-on-submit,
|
||||||
|
** and action buttons.
|
||||||
|
***************************************************************************/
|
||||||
|
function blockWidgetActionCallback(blockData: BlockData, eventValues?: { [name: string]: any }): boolean
|
||||||
|
{
|
||||||
|
console.log(`in blockWidgetActionCallback, called by block: ${JSON.stringify(blockData)}`);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if the eventValues included an actionCode - validate it before proceeding //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
if (eventValues && eventValues.actionCode && !ProcessWidgetBlockUtils.isActionCodeValid(eventValues.actionCode, activeStep, processValues))
|
||||||
|
{
|
||||||
|
setFormError("Unrecognized action code: " + eventValues.actionCode);
|
||||||
|
|
||||||
|
if (eventValues["_fieldToClearIfError"])
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if the eventValues included a _fieldToClearIfError, well, then do that. //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
formikSetFieldValueFunction(eventValues["_fieldToClearIfError"], "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// ok - submit! //
|
||||||
|
//////////////////
|
||||||
|
handleSubmit(eventValues);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
** in a memoized-fashion (YUNO useMemo?), render a component that is an
|
||||||
|
** adHoc widget (e.g., composite)
|
||||||
|
***************************************************************************/
|
||||||
|
function renderAdHocWidget(componentValues: any, componentIndex: number)
|
||||||
|
{
|
||||||
|
const key = activeStep.name + "-" + stepInstanceCounter + "-" + componentIndex;
|
||||||
|
if (renderedWidgets[key])
|
||||||
|
{
|
||||||
|
return renderedWidgets[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
const widgetMetaData = new QWidgetMetaData({name: "adHoc"});
|
||||||
|
const compositeWidgetData = JSON.parse(JSON.stringify(componentValues)) as CompositeData;
|
||||||
|
compositeWidgetData.styleOverrides = {py: "0.5rem", display: "flex", flexDirection: "column", gap: "0.5rem"};
|
||||||
|
|
||||||
|
ProcessWidgetBlockUtils.dynamicEvaluationOfCompositeWidgetData(compositeWidgetData, processValues);
|
||||||
|
|
||||||
|
renderedWidgets[key] = <Box key={key} pt={2}>
|
||||||
|
<CompositeWidget widgetMetaData={widgetMetaData} data={compositeWidgetData} actionCallback={blockWidgetActionCallback} />
|
||||||
|
</Box>;
|
||||||
|
|
||||||
|
setRenderedWidgets(renderedWidgets);
|
||||||
|
|
||||||
|
return (renderedWidgets[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// generate the main form body content for a step //
|
// generate the main form body content for a step //
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
@ -384,7 +479,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
if (qJobRunning || step === null)
|
if (qJobRunning || step === null)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<Grid m={3} mt={9} container>
|
<Grid m={3} mt={9} container maxWidth="calc(100% - 3rem)">
|
||||||
<Grid item xs={0} lg={3} />
|
<Grid item xs={0} lg={3} />
|
||||||
<Grid item xs={12} lg={6}>
|
<Grid item xs={12} lg={6}>
|
||||||
<Card>
|
<Card>
|
||||||
@ -765,8 +860,29 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
component.type === QComponentType.WIDGET && (
|
component.type === QComponentType.WIDGET && (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
// if a widget name is given, render that widget //
|
||||||
|
///////////////////////////////////////////////////
|
||||||
component.values?.widgetName &&
|
component.values?.widgetName &&
|
||||||
renderWidget(component.values?.widgetName)
|
renderWidget(component.values?.widgetName)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
// if the widget is marked as adHoc, render it as such //
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
component.values?.isAdHocWidget &&
|
||||||
|
renderAdHocWidget(component.values, index)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// if neither of those, then programmer error //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
!(component.values?.widgetName || component.values?.isAdHocWidget) &&
|
||||||
|
<Alert severity="error">Error: Component is marked as WIDGET type, but does not specify a <u>widgetName</u>, nor the <u>isAdHocWidget</u> flag.</Alert>
|
||||||
|
}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -866,6 +982,11 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
setActiveStepIndex(newIndex);
|
setActiveStepIndex(newIndex);
|
||||||
setOverrideOnLastStep(null);
|
setOverrideOnLastStep(null);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// reset formik touched data, so a field that's repeated doesn't immediately show a 'dirty' state //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
formikSetTouched({}, false);
|
||||||
|
|
||||||
if (steps)
|
if (steps)
|
||||||
{
|
{
|
||||||
const activeStep = steps[newIndex];
|
const activeStep = steps[newIndex];
|
||||||
@ -911,6 +1032,16 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
addField("googleDriveFolderName", {type: "hidden", omitFromQDynamicForm: true}, "", null);
|
addField("googleDriveFolderName", {type: "hidden", omitFromQDynamicForm: true}, "", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doesStepHaveComponent(activeStep, QComponentType.WIDGET))
|
||||||
|
{
|
||||||
|
ProcessWidgetBlockUtils.addFieldsForCompositeWidget(activeStep, (fieldMetaData) =>
|
||||||
|
{
|
||||||
|
const dynamicField = DynamicFormUtils.getDynamicField(fieldMetaData);
|
||||||
|
const validation = DynamicFormUtils.getValidationForField(fieldMetaData);
|
||||||
|
addField(fieldMetaData.name, dynamicField, processValues[fieldMetaData.name], validation)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
// if this step has form fields, set up the form //
|
// if this step has form fields, set up the form //
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
@ -1099,7 +1230,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
if (updatedFields)
|
if (updatedFields)
|
||||||
{
|
{
|
||||||
updatedFields.forEach((field) => previouslySeenUpdatedFieldMetaDataMap.set(field.name, field));
|
updatedFields.forEach((field) => previouslySeenUpdatedFieldMetaDataMap.set(field.name, field));
|
||||||
setPreviouslySeenUpdatedFieldMetaDataMap(previouslySeenUpdatedFieldMetaDataMap)
|
setPreviouslySeenUpdatedFieldMetaDataMap(previouslySeenUpdatedFieldMetaDataMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let step of steps)
|
for (let step of steps)
|
||||||
@ -1210,6 +1341,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
setNewStep(nextStepName);
|
setNewStep(nextStepName);
|
||||||
setStepInstanceCounter(1 + stepInstanceCounter);
|
setStepInstanceCounter(1 + stepInstanceCounter);
|
||||||
setProcessValues(newValues);
|
setProcessValues(newValues);
|
||||||
|
setRenderedWidgets({});
|
||||||
setQJobRunning(null);
|
setQJobRunning(null);
|
||||||
|
|
||||||
if (formikSetFieldValueFunction)
|
if (formikSetFieldValueFunction)
|
||||||
@ -1465,8 +1597,9 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// handle user submitting the form - which in qqq means moving forward from any screen. //
|
// handle user submitting the form - which in qqq means moving forward from any screen. //
|
||||||
|
// caller can pass in a map of values to be added to the form data too //
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const handleSubmit = async (values: any, actions: any) =>
|
const handleSubmit = async (values: any) =>
|
||||||
{
|
{
|
||||||
setFormError(null);
|
setFormError(null);
|
||||||
|
|
||||||
@ -1556,14 +1689,40 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const mainCardStyles: any = {};
|
|
||||||
const formStyles: any = {};
|
const formStyles: any = {};
|
||||||
|
if(isWidget)
|
||||||
|
{
|
||||||
|
formStyles.display = "flex";
|
||||||
|
formStyles.flexGrow = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
function makeMainCardStyles(theme: Theme)
|
||||||
|
{
|
||||||
|
const mainCardStyles: any = {};
|
||||||
|
|
||||||
|
if(!isWidget && !isModal)
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// remove margin around card for non-widget, non-modal, small //
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
mainCardStyles[theme.breakpoints.down("sm")] = {
|
||||||
|
marginLeft: "-1.5rem",
|
||||||
|
marginRight: "-1.5rem",
|
||||||
|
borderRadius: "0"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
mainCardStyles.minHeight = `calc(100vh - ${isModal ? 150 : 400}px)`;
|
mainCardStyles.minHeight = `calc(100vh - ${isModal ? 150 : 400}px)`;
|
||||||
if (!processError && (qJobRunning || activeStep === null) && !isModal && !isWidget)
|
if (!processError && (qJobRunning || activeStep === null) && !isModal && !isWidget)
|
||||||
{
|
{
|
||||||
mainCardStyles.background = "#FFFFFF";
|
mainCardStyles.background = "#FFFFFF";
|
||||||
mainCardStyles.boxShadow = "none";
|
mainCardStyles.boxShadow = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWidget)
|
if (isWidget)
|
||||||
{
|
{
|
||||||
mainCardStyles.background = "none";
|
mainCardStyles.background = "none";
|
||||||
@ -1573,8 +1732,9 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
mainCardStyles.alignItems = "stretch";
|
mainCardStyles.alignItems = "stretch";
|
||||||
mainCardStyles.flexGrow = 1;
|
mainCardStyles.flexGrow = 1;
|
||||||
mainCardStyles.display = "flex";
|
mainCardStyles.display = "flex";
|
||||||
formStyles.display = "flex";
|
}
|
||||||
formStyles.flexGrow = 1;
|
|
||||||
|
return mainCardStyles
|
||||||
}
|
}
|
||||||
|
|
||||||
let nextButtonLabel = "Next";
|
let nextButtonLabel = "Next";
|
||||||
@ -1602,20 +1762,21 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
{({
|
{({
|
||||||
values, errors, touched, isSubmitting, setFieldValue,
|
values, errors, touched, isSubmitting, setFieldValue, setTouched
|
||||||
}) =>
|
}) =>
|
||||||
{
|
{
|
||||||
///////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// once we're in the formik form, use its setFieldValue function //
|
// once we're in the formik form, capture some of its functions //
|
||||||
// over top of the default one we created globally //
|
// over top of the default ones we created globally //
|
||||||
///////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
formikSetFieldValueFunction = setFieldValue;
|
formikSetFieldValueFunction = setFieldValue;
|
||||||
|
formikSetTouched = setTouched;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form style={formStyles} id={formId} autoComplete="off">
|
<Form style={formStyles} id={formId} autoComplete="off">
|
||||||
<Card sx={mainCardStyles}>
|
<Card sx={makeMainCardStyles}>
|
||||||
{
|
{
|
||||||
!isWidget && (
|
!isWidget && processMetaData?.stepFlow == "LINEAR" && (
|
||||||
<Box mx={2} mt={-3} sx={{"& .MuiStepper-horizontal": {minHeight: "5rem"}}}>
|
<Box mx={2} mt={-3} sx={{"& .MuiStepper-horizontal": {minHeight: "5rem"}}}>
|
||||||
<Stepper activeStep={activeStepIndex} alternativeLabel>
|
<Stepper activeStep={activeStepIndex} alternativeLabel>
|
||||||
{steps.map((step) => (
|
{steps.map((step) => (
|
||||||
@ -1650,7 +1811,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
{/********************************
|
{/********************************
|
||||||
** back &| next/submit buttons **
|
** back &| next/submit buttons **
|
||||||
********************************/}
|
********************************/}
|
||||||
<Box mt={6} width="100%" display="flex" justifyContent="space-between" position={isWidget ? "absolute" : "initial"} bottom={isWidget ? "3rem" : "initial"} right={isWidget ? "1.5rem" : "initial"}>
|
<Box mt={3} width="100%" display="flex" justifyContent="space-between" position={isWidget ? "absolute" : "initial"} bottom={isWidget ? "3rem" : "initial"} right={isWidget ? "1.5rem" : "initial"}>
|
||||||
{true || activeStepIndex === 0 ? (
|
{true || activeStepIndex === 0 ? (
|
||||||
<Box />
|
<Box />
|
||||||
) : (
|
) : (
|
||||||
@ -1660,11 +1821,6 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
<Box />
|
<Box />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{formError && (
|
|
||||||
<MDTypography component="div" variant="caption" color="error" fontWeight="regular" align="right" fullWidth>
|
|
||||||
{formError}
|
|
||||||
</MDTypography>
|
|
||||||
)}
|
|
||||||
{
|
{
|
||||||
noMoreSteps && <QCancelButton
|
noMoreSteps && <QCancelButton
|
||||||
onClickHandler={() => handleCancelClicked(true)}
|
onClickHandler={() => handleCancelClicked(true)}
|
||||||
@ -1700,9 +1856,10 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
|||||||
|
|
||||||
const body = (
|
const body = (
|
||||||
<Box py={3} mb={20} className="processRun">
|
<Box py={3} mb={20} className="processRun">
|
||||||
<Grid container justifyContent="center" alignItems="center" sx={{height: "100%", mt: 8}}>
|
<Grid container justifyContent="center" alignItems="center" mt={{xs: 0, md: 6}} sx={{height: "100%"}}>
|
||||||
<Grid item xs={12} lg={10} xl={8}>
|
<Grid item xs={12} lg={10} xl={8}>
|
||||||
{form}
|
{form}
|
||||||
|
{formError && <Alert severity="error" onClose={() => setFormError(null)} sx={{position: "fixed", top: "40px", left: "10vw", width: "calc(80vw)", zIndex: "99999"}}>{formError}</Alert>}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
Reference in New Issue
Block a user