diff --git a/src/qqq/pages/process-run/components/QProcessSummaryResults.tsx b/src/qqq/pages/process-run/components/QProcessSummaryResults.tsx index f4a1ac5..68f5b83 100644 --- a/src/qqq/pages/process-run/components/QProcessSummaryResults.tsx +++ b/src/qqq/pages/process-run/components/QProcessSummaryResults.tsx @@ -48,15 +48,17 @@ function QProcessSummaryResults({ qInstance, process, table = null, processValues, step, }: Props): JSX.Element { + const sourceTable = qInstance.tables.get(processValues.sourceTable); + const resultValidationList = ( { - processValues?.recordCount && table && ( + processValues?.recordCount !== undefined && sourceTable && ( {processValues.recordCount.toLocaleString()} {" "} - {table.label} + {sourceTable.label} {" "} records were processed. @@ -65,7 +67,7 @@ function QProcessSummaryResults({ } { - processValues.processResults && processValues.processResults.map((processSummaryLine: ProcessSummaryLine, i: number) => (new ProcessSummaryLine(processSummaryLine).getProcessSummaryListItem(i, table, qInstance, true))) + processValues.processResults && processValues.processResults.map((processSummaryLine: ProcessSummaryLine, i: number) => (new ProcessSummaryLine(processSummaryLine).getProcessSummaryListItem(i, sourceTable, qInstance, true))) } @@ -79,8 +81,8 @@ function QProcessSummaryResults({ - {process.iconName} - {`${process.label} : ${step.label}`} + {process.iconName && {process.iconName}} + Process Summary {resultValidationList} diff --git a/src/qqq/pages/process-run/components/QValidationReview.tsx b/src/qqq/pages/process-run/components/QValidationReview.tsx index d5f4357..472a17c 100644 --- a/src/qqq/pages/process-run/components/QValidationReview.tsx +++ b/src/qqq/pages/process-run/components/QValidationReview.tsx @@ -64,6 +64,7 @@ function QValidationReview({ }: Props): JSX.Element { const [previewRecordIndex, setPreviewRecordIndex] = useState(0); + const sourceTable = qInstance.tables.get(processValues.sourceTable); const updatePreviewRecordIndex = (offset: number) => { @@ -89,15 +90,44 @@ function QValidationReview({ }, }); + const buildDoFullValidationRadioListItem = (value: "true" | "false", labelText: string, tooltipHTML: JSX.Element): JSX.Element => + { + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // split up the label into words - then we'll display the last word by itself with a non-breaking space, no-wrap-glued to the button. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const labelWords = labelText.split(" "); + const lastWord = labelWords[labelWords.length - 1]; + labelWords.splice(labelWords.length - 1, 1); + + return ( + + } + label={( + + {`${labelWords.join(" ")} `} + + {/* eslint-disable-next-line react/jsx-one-expression-per-line */} + {lastWord}.  + info_outlined + {/* eslint-disable-next-line react/jsx-closing-tag-location */} + + + + )} + /> + + ); + }; + const preValidationList = ( { - processValues?.recordCount && table && ( + processValues?.recordCount !== undefined && sourceTable && ( - You selected - {` ${processValues.recordCount.toLocaleString()} ${table?.label} `} - records. + {`Input: ${processValues.recordCount.toLocaleString()} ${sourceTable?.label} record${processValues.recordCount === 1 ? "" : "s"}.`} ) @@ -108,59 +138,36 @@ function QValidationReview({ How would you like to proceed? - + - - } - label={( - - Perform Validation on all records before processing. - - If you choose this option, a Validation step will run on all of the records that you selected. - You will then be told how many can process successfully, and how many have issues. -
-
- Running this validation may take several minutes, depending on the complexity of the work, and the number of records. -
-
- Choose this option if you want more information about what will happen, and you are willing to wait for that information. - - )} - > - info_outlined -
-
- )} - /> -
- - } - label={( - - Skip Validation. Submit the records for immediate processing. - - If you choose this option, the records you selected will immediately be processed. - You will be told how many records were successfully processed, and which ones had issues after the processing is completed. -
-
- Choose this option if you feel that you do not need this information, or are not willing to wait for it. - - )} - > - info_outlined -
-
- )} - /> -
+ {buildDoFullValidationRadioListItem( + "true", + "Perform Validation on all records before processing", ( +
+ If you choose this option, a Validation step will run on all of the input records. + You will then be told how many can process successfully, and how many have issues. +
+
+ Running this validation may take several minutes, depending on the complexity of the work, and the number of records. +
+
+ Choose this option if you want more information about what will happen, and you are willing to wait for that information. +
+ ), + )} + + {buildDoFullValidationRadioListItem( + "false", + "Skip Validation. Submit the records for immediate processing", ( +
+ If you choose this option, the records input records will immediately be processed. + You will be told how many records were successfully processed, and which ones had issues after the processing is completed. +
+
+ Choose this option if you feel that you do not need this information, or are not willing to wait for it. +
+ ), + )}
@@ -172,11 +179,11 @@ function QValidationReview({ const postValidationList = ( { - processValues?.recordCount && table && ( + processValues?.recordCount !== undefined && sourceTable && ( Validation complete on - {` ${processValues.recordCount.toLocaleString()} ${table?.label} `} + {` ${processValues.recordCount.toLocaleString()} ${sourceTable?.label} `} records. @@ -184,7 +191,7 @@ function QValidationReview({ } { - processValues.validationSummary && processValues.validationSummary.map((processSummaryLine: ProcessSummaryLine, i: number) => (new ProcessSummaryLine(processSummaryLine).getProcessSummaryListItem(i, table, qInstance))) + processValues.validationSummary && processValues.validationSummary.map((processSummaryLine: ProcessSummaryLine, i: number) => (new ProcessSummaryLine(processSummaryLine).getProcessSummaryListItem(i, sourceTable, qInstance))) } @@ -199,9 +206,9 @@ function QValidationReview({ { - previewRecords && previewRecords.length > 0 ? ( + processValues?.previewMessage && previewRecords && previewRecords.length > 0 ? ( <> - This is a preview of the records that will be created. + {processValues?.previewMessage} diff --git a/src/qqq/pages/process-run/index.tsx b/src/qqq/pages/process-run/index.tsx index 262b07a..b06e0db 100644 --- a/src/qqq/pages/process-run/index.tsx +++ b/src/qqq/pages/process-run/index.tsx @@ -21,7 +21,9 @@ import * as Yup from "yup"; -import {CircularProgress, TablePagination} from "@mui/material"; +import { + Button, CircularProgress, Icon, TablePagination, +} from "@mui/material"; import {DataGridPro, GridColDef} from "@mui/x-data-grid-pro"; // formik components import {Form, Formik} from "formik"; @@ -96,8 +98,13 @@ function ProcessRun({process}: Props): JSX.Element const [lastProcessResponse, setLastProcessResponse] = useState( null as QJobStarted | QJobComplete | QJobError | QJobRunning, ); + const [showErrorDetail, setShowErrorDetail] = useState(false); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // the validation screen - it can change whether next is actually the final step or not... so, use this state field to track that. // + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const [overrideOnLastStep, setOverrideOnLastStep] = useState(null as boolean); + const onLastStep = activeStepIndex === steps.length - 2; const noMoreSteps = activeStepIndex === steps.length - 1; @@ -199,6 +206,11 @@ function ProcessRun({process}: Props): JSX.Element return ({value}); }; + const toggleShowErrorDetail = () => + { + setShowErrorDetail(!showErrorDetail); + }; + //////////////////////////////////////////////////// // generate the main form body content for a step // //////////////////////////////////////////////////// @@ -216,11 +228,24 @@ function ProcessRun({process}: Props): JSX.Element { return ( <> - + Error - {processError} + An error occurred while running the process: + {" "} + {process.label} + + + + + {processError} + + + ); @@ -326,8 +351,7 @@ function ProcessRun({process}: Props): JSX.Element ////////////////////////////////////////////////////////////// setFieldValue("doFullValidation", value); - // eslint-disable-next-line no-unneeded-ternary - setOverrideOnLastStep(value === "true" ? false : true); + setOverrideOnLastStep(value !== "true"); }} /> ) @@ -823,6 +847,7 @@ function ProcessRun({process}: Props): JSX.Element setProcessValues({}); setRecords([]); + setOverrideOnLastStep(null); setLastProcessResponse(new QJobRunning({message: "Working..."})); setTimeout(async () => @@ -848,7 +873,7 @@ function ProcessRun({process}: Props): JSX.Element const mainCardStyles: any = {}; mainCardStyles.minHeight = "calc(100vh - 400px)"; - if (qJobRunning || activeStep === null) + if (!processError && (qJobRunning || activeStep === null)) { mainCardStyles.background = "none"; mainCardStyles.boxShadow = "none"; diff --git a/src/qqq/pages/process-run/model/ProcessSummaryLine.tsx b/src/qqq/pages/process-run/model/ProcessSummaryLine.tsx index 55dacf9..04a0b3d 100644 --- a/src/qqq/pages/process-run/model/ProcessSummaryLine.tsx +++ b/src/qqq/pages/process-run/model/ProcessSummaryLine.tsx @@ -59,24 +59,37 @@ export class ProcessSummaryLine getProcessSummaryListItem(i: number, table: QTableMetaData, qInstance: QInstance, isResultScreen: boolean = false): JSX.Element { + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // split up the message into words - then we'll display the last word by itself with a non-breaking space, no-wrap-glued to the button. // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const messageWords = this.message ? this.message.split(" ") : []; + const lastWord = messageWords.length > 1 ? messageWords[messageWords.length - 1] : ""; + if (messageWords.length > 1) + { + messageWords.splice(messageWords.length - 1, 1); + } + return ( {this.getIcon(isResultScreen)} - {this.count.toLocaleString()} - {" "} - {this.message} + {/* work hard to prevent the icon from falling down to the next line by itself... */} + {`${this.count.toLocaleString()} ${messageWords.join(" ")} `} + { + (table && this.primaryKeys) ? ( + + {/* eslint-disable-next-line react/jsx-one-expression-per-line */} + {lastWord}  + + open_in_new + + {/* eslint-disable-next-line react/jsx-closing-tag-location */} + + + ) : {lastWord} + } - { - table && this.primaryKeys && ( - - - open_in_new - - - ) - } ); @@ -131,8 +144,6 @@ export class ProcessSummaryLine { const tablePath = qInstance.getTablePath(table); const filter = new QQueryFilter([new QFilterCriteria(table.primaryKeyField, QCriteriaOperator.IN, this.primaryKeys)]); - console.log("Link to records:"); - console.log(filter); return (`${tablePath}?filter=${JSON.stringify(filter)}`); } } diff --git a/src/qqq/styles/qqq-override-styles.css b/src/qqq/styles/qqq-override-styles.css index 4f865a0..4559740 100644 --- a/src/qqq/styles/qqq-override-styles.css +++ b/src/qqq/styles/qqq-override-styles.css @@ -110,3 +110,10 @@ margin-left: 40px; font-size: 14px; } + +/* Help make the radio, text, and icon wrap in a good way */ +.doFullValidationRadios label +{ + display: flex; + align-items: flex-start; +}