mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-21 22:58:43 +00:00
CE-1946: checkpoint initial commit
This commit is contained in:
@ -66,6 +66,7 @@ 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 {ChildRecordListData} from "qqq/components/widgets/misc/RecordGridWidget";
|
||||
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";
|
||||
@ -150,7 +151,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
const [previouslySeenUpdatedFieldMetaDataMap, setPreviouslySeenUpdatedFieldMetaDataMap] = useState(new Map<string, QFieldMetaData>);
|
||||
|
||||
const [renderedWidgets, setRenderedWidgets] = useState({} as { [step: string]: { [widgetName: string]: any } });
|
||||
const [controlCallbacks, setControlCallbacks] = useState({} as {[name: string]: () => void})
|
||||
const [controlCallbacks, setControlCallbacks] = useState({} as { [name: string]: () => void });
|
||||
|
||||
const {pageHeader, recordAnalytics, setPageHeader, helpHelpActive} = useContext(QContext);
|
||||
|
||||
@ -185,7 +186,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
{
|
||||
noMoreSteps = true;
|
||||
}
|
||||
if(processValues["noMoreSteps"])
|
||||
if (processValues["noMoreSteps"])
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// this, to allow a non-linear process to request this behavior //
|
||||
@ -210,7 +211,8 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
const [recordConfig, setRecordConfig] = useState({} as any);
|
||||
const [pageNumber, setPageNumber] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const [records, setRecords] = useState([] as QRecord[]);
|
||||
const [records, setRecords] = useState([] as any);
|
||||
const [childRecordData, setChildRecordData] = useState(null as ChildRecordListData);
|
||||
|
||||
//////////////////////////////
|
||||
// state for bulk edit form //
|
||||
@ -329,23 +331,24 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
*******************************************************************************/
|
||||
function renderWidget(widgetName: string)
|
||||
{
|
||||
const widgetMetaData = qInstance.widgets.get(widgetName);
|
||||
if (!widgetMetaData)
|
||||
{
|
||||
return (<Alert color="error">Unrecognized widget name: {widgetName}</Alert>);
|
||||
}
|
||||
|
||||
if (!renderedWidgets[activeStep.name])
|
||||
{
|
||||
renderedWidgets[activeStep.name] = {};
|
||||
setRenderedWidgets(renderedWidgets);
|
||||
}
|
||||
|
||||
if (renderedWidgets[activeStep.name][widgetName])
|
||||
let isChildRecordWidget = widgetMetaData.type == "childRecordList";
|
||||
if (!isChildRecordWidget && renderedWidgets[activeStep.name][widgetName])
|
||||
{
|
||||
return renderedWidgets[activeStep.name][widgetName];
|
||||
}
|
||||
|
||||
const widgetMetaData = qInstance.widgets.get(widgetName);
|
||||
if (!widgetMetaData)
|
||||
{
|
||||
return (<Alert color="error">Unrecognized widget name: {widgetName}</Alert>);
|
||||
}
|
||||
|
||||
const queryStringParts: string[] = [];
|
||||
for (let name in processValues)
|
||||
{
|
||||
@ -353,14 +356,25 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
}
|
||||
|
||||
let initialWidgetDataList = null;
|
||||
if(processValues[widgetName])
|
||||
if (processValues[widgetName])
|
||||
{
|
||||
processValues[widgetName].hasPermission = true
|
||||
initialWidgetDataList = [processValues[widgetName]]
|
||||
processValues[widgetName].hasPermission = true;
|
||||
initialWidgetDataList = [processValues[widgetName]];
|
||||
}
|
||||
|
||||
let actionCallback = blockWidgetActionCallback;
|
||||
if (isChildRecordWidget)
|
||||
{
|
||||
actionCallback = childRecordListWidgetActionCallBack;
|
||||
|
||||
if (childRecordData)
|
||||
{
|
||||
initialWidgetDataList = [childRecordData];
|
||||
}
|
||||
}
|
||||
|
||||
const renderedWidget = (<Box m={-2}>
|
||||
<DashboardWidgets widgetMetaDataList={[widgetMetaData]} omitWrappingGridContainer={true} childUrlParams={queryStringParts.join("&")} initialWidgetDataList={initialWidgetDataList} values={processValues} actionCallback={blockWidgetActionCallback} />
|
||||
<DashboardWidgets widgetMetaDataList={[widgetMetaData]} omitWrappingGridContainer={true} childUrlParams={queryStringParts.join("&")} initialWidgetDataList={initialWidgetDataList} values={processValues} actionCallback={actionCallback} />
|
||||
</Box>);
|
||||
renderedWidgets[activeStep.name][widgetName] = renderedWidget;
|
||||
return renderedWidget;
|
||||
@ -374,46 +388,57 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
{
|
||||
const split = controlCode.split(":", 2);
|
||||
let controlCallbackName: string;
|
||||
let controlCallbackValue: any
|
||||
if(split.length == 2)
|
||||
let controlCallbackValue: any;
|
||||
if (split.length == 2)
|
||||
{
|
||||
if(split[0] == "showModal")
|
||||
if (split[0] == "showModal")
|
||||
{
|
||||
processValues[split[1]] = true
|
||||
controlCallbackName = split[1]
|
||||
controlCallbackValue = true
|
||||
processValues[split[1]] = true;
|
||||
controlCallbackName = split[1];
|
||||
controlCallbackValue = true;
|
||||
}
|
||||
else if(split[0] == "hideModal")
|
||||
else if (split[0] == "hideModal")
|
||||
{
|
||||
processValues[split[1]] = false
|
||||
controlCallbackName = split[1]
|
||||
controlCallbackValue = false
|
||||
processValues[split[1]] = false;
|
||||
controlCallbackName = split[1];
|
||||
controlCallbackValue = false;
|
||||
}
|
||||
else if(split[0] == "toggleModal")
|
||||
else if (split[0] == "toggleModal")
|
||||
{
|
||||
const currentValue = processValues[split[1]]
|
||||
const currentValue = processValues[split[1]];
|
||||
processValues[split[1]] = !!!currentValue;
|
||||
controlCallbackName = split[1]
|
||||
controlCallbackValue = processValues[split[1]]
|
||||
controlCallbackName = split[1];
|
||||
controlCallbackValue = processValues[split[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(`Unexpected part[0] (before colon) in controlCode: [${controlCode}]`)
|
||||
console.log(`Unexpected part[0] (before colon) in controlCode: [${controlCode}]`);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(`Expected controlCode to have 2 colon-delimited parts, but was: [${controlCode}]`)
|
||||
console.log(`Expected controlCode to have 2 colon-delimited parts, but was: [${controlCode}]`);
|
||||
}
|
||||
|
||||
if(controlCallbackName && controlCallbacks[controlCallbackName])
|
||||
if (controlCallbackName && controlCallbacks[controlCallbackName])
|
||||
{
|
||||
// @ts-ignore ... args are hard
|
||||
controlCallbacks[controlCallbackName](controlCallbackValue)
|
||||
controlCallbacks[controlCallbackName](controlCallbackValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** callback used by child list widget
|
||||
***************************************************************************/
|
||||
function childRecordListWidgetActionCallBack(data: any): boolean
|
||||
{
|
||||
console.log(`in childRecordListWidgetActionCallBack: ${JSON.stringify(data)}`);
|
||||
setChildRecordData(data as ChildRecordListData);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** callback used by widget blocks, e.g., for input-text-enter-on-submit,
|
||||
** and action buttons.
|
||||
@ -422,11 +447,11 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
{
|
||||
console.log(`in blockWidgetActionCallback, called by block: ${JSON.stringify(blockData)}`);
|
||||
|
||||
if(eventValues?.registerControlCallbackName && eventValues?.registerControlCallbackFunction)
|
||||
if (eventValues?.registerControlCallbackName && eventValues?.registerControlCallbackFunction)
|
||||
{
|
||||
controlCallbacks[eventValues.registerControlCallbackName] = eventValues.registerControlCallbackFunction;
|
||||
setControlCallbacks(controlCallbacks)
|
||||
return (true)
|
||||
setControlCallbacks(controlCallbacks);
|
||||
return (true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -449,29 +474,29 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
// }
|
||||
|
||||
let doSubmit = false;
|
||||
if(blockData?.blockTypeName == "BUTTON" && eventValues?.actionCode)
|
||||
if (blockData?.blockTypeName == "BUTTON" && eventValues?.actionCode)
|
||||
{
|
||||
doSubmit = true
|
||||
doSubmit = true;
|
||||
}
|
||||
else if(blockData?.blockTypeName == "BUTTON" && eventValues?.controlCode)
|
||||
else if (blockData?.blockTypeName == "BUTTON" && eventValues?.controlCode)
|
||||
{
|
||||
handleControlCode(eventValues.controlCode);
|
||||
doSubmit = false
|
||||
doSubmit = false;
|
||||
}
|
||||
else if(blockData?.blockTypeName == "INPUT_FIELD")
|
||||
else if (blockData?.blockTypeName == "INPUT_FIELD")
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if action callback was fired from an input field, assume that means we're good to submit. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
doSubmit = true
|
||||
doSubmit = true;
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// ok - submit! //
|
||||
//////////////////
|
||||
if(doSubmit)
|
||||
if (doSubmit)
|
||||
{
|
||||
handleSubmit(eventValues);
|
||||
handleFormSubmit(eventValues);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
@ -658,7 +683,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
let helpRoles = ["PROCESS_SCREEN", "ALL_SCREENS"];
|
||||
const showHelp = helpHelpActive || hasHelpContent(step.helpContents, helpRoles);
|
||||
const formattedHelpContent = <HelpContent helpContents={step.helpContents} roles={helpRoles} helpContentKey={`process:${processName};step:${step?.name}`} />;
|
||||
const isFormatScanner = step?.format?.toLowerCase() == "scanner"
|
||||
const isFormatScanner = step?.format?.toLowerCase() == "scanner";
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -965,7 +990,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
// 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>
|
||||
<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>
|
||||
}
|
||||
</>
|
||||
)
|
||||
@ -1114,7 +1139,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
// if this is the last step or not - and by default that radio will be true, to make this //
|
||||
// NOT the last step - so set this value. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(!processValues["validationSummary"] && processValues["supportsFullValidation"])
|
||||
if (!processValues["validationSummary"] && processValues["supportsFullValidation"])
|
||||
{
|
||||
setOverrideOnLastStep(false);
|
||||
}
|
||||
@ -1133,7 +1158,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
{
|
||||
const dynamicField = DynamicFormUtils.getDynamicField(fieldMetaData);
|
||||
const validation = DynamicFormUtils.getValidationForField(fieldMetaData);
|
||||
addField(fieldMetaData.name, dynamicField, processValues[fieldMetaData.name], validation)
|
||||
addField(fieldMetaData.name, dynamicField, processValues[fieldMetaData.name], validation);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1295,6 +1320,11 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
const {records} = response;
|
||||
setRecords(records);
|
||||
|
||||
if (!childRecordData || childRecordData.length == 0)
|
||||
{
|
||||
setChildRecordData(convertRecordsToChildRecordData(records));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// re-construct the recordConfig object, so the setState call triggers a new rendering //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1317,6 +1347,30 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
}, [needRecords]);
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
function convertRecordsToChildRecordData(records: QRecord[])
|
||||
{
|
||||
const frontendRecords = [] as any[];
|
||||
records.forEach((record: QRecord) =>
|
||||
{
|
||||
const object = {
|
||||
"tableName": record.tableName,
|
||||
"recordLabel": record.recordLabel,
|
||||
"errors": record.errors,
|
||||
"warnings": record.warnings,
|
||||
"values": Object.fromEntries(record.values),
|
||||
"displayValues": Object.fromEntries(record.displayValues),
|
||||
};
|
||||
frontendRecords.push(object);
|
||||
});
|
||||
const newChildListData = {} as ChildRecordListData;
|
||||
newChildListData.queryOutput = {records: frontendRecords};
|
||||
return (newChildListData);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -1690,11 +1744,35 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
setNewStep(activeStepIndex - 1);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////
|
||||
// handle user submitting changed records //
|
||||
////////////////////////////////////////////
|
||||
const doSubmit = async (formData: FormData) =>
|
||||
{
|
||||
const formDataHeaders = {
|
||||
"content-type": "multipart/form-data; boundary=--------------------------320289315924586491558366",
|
||||
};
|
||||
|
||||
setTimeout(async () =>
|
||||
{
|
||||
recordAnalytics({category: "processEvents", action: "processStep", label: activeStep.label});
|
||||
|
||||
const processResponse = await Client.getInstance().processStep(
|
||||
processName,
|
||||
processUUID,
|
||||
activeStep.name,
|
||||
formData,
|
||||
formDataHeaders
|
||||
);
|
||||
setLastProcessResponse(processResponse);
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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) =>
|
||||
const handleFormSubmit = async (values: any) =>
|
||||
{
|
||||
setFormError(null);
|
||||
|
||||
@ -1733,28 +1811,20 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
formData.append("bulkEditEnabledFields", bulkEditEnabledFields.join(","));
|
||||
}
|
||||
|
||||
const formDataHeaders = {
|
||||
"content-type": "multipart/form-data; boundary=--------------------------320289315924586491558366",
|
||||
};
|
||||
/////////////////////////////////////////////////////////////
|
||||
// convert to regular objects so that they can be jsonized //
|
||||
/////////////////////////////////////////////////////////////
|
||||
if (childRecordData)
|
||||
{
|
||||
formData.append("frontendRecords", JSON.stringify(childRecordData.queryOutput.records));
|
||||
}
|
||||
|
||||
setProcessValues({});
|
||||
setRecords([]);
|
||||
setOverrideOnLastStep(null);
|
||||
setLastProcessResponse(new QJobRunning({message: "Working..."}));
|
||||
|
||||
setTimeout(async () =>
|
||||
{
|
||||
recordAnalytics({category: "processEvents", action: "processStep", label: activeStep.label});
|
||||
|
||||
const processResponse = await Client.getInstance().processStep(
|
||||
processName,
|
||||
processUUID,
|
||||
activeStep.name,
|
||||
formData,
|
||||
formDataHeaders,
|
||||
);
|
||||
setLastProcessResponse(processResponse);
|
||||
});
|
||||
doSubmit(formData);
|
||||
};
|
||||
|
||||
|
||||
@ -1785,7 +1855,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
|
||||
|
||||
const formStyles: any = {};
|
||||
if(isWidget)
|
||||
if (isWidget)
|
||||
{
|
||||
formStyles.display = "flex";
|
||||
formStyles.flexGrow = 1;
|
||||
@ -1799,7 +1869,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
{
|
||||
const mainCardStyles: any = {};
|
||||
|
||||
if(!isWidget && !isModal)
|
||||
if (!isWidget && !isModal)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// remove margin around card for non-widget, non-modal, small //
|
||||
@ -1829,7 +1899,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
mainCardStyles.display = "flex";
|
||||
}
|
||||
|
||||
return mainCardStyles
|
||||
return mainCardStyles;
|
||||
}
|
||||
|
||||
let nextButtonLabel = "Next";
|
||||
@ -1854,7 +1924,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationScheme}
|
||||
validation={validationFunction}
|
||||
onSubmit={handleSubmit}
|
||||
onSubmit={handleFormSubmit}
|
||||
>
|
||||
{({
|
||||
values, errors, touched, isSubmitting, setFieldValue, setTouched
|
||||
|
Reference in New Issue
Block a user