diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index a031ef1..0000000 --- a/cypress.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {defineConfig} from "cypress"; - -export default defineConfig({ - e2e: { - viewportHeight: 1000, - viewportWidth: 1200, - setupNodeEvents(on, config) - { - // implement node event listeners here - }, - }, -}); diff --git a/package.json b/package.json index cb85d4f..feb4fdd 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "@auth0/auth0-react": "1.10.2", "@emotion/react": "11.7.1", "@emotion/styled": "11.6.0", - "@kingsrook/qqq-frontend-core": "1.0.101", + "@kingsrook/qqq-frontend-core": "1.0.102", "@mui/icons-material": "5.4.1", "@mui/material": "5.11.1", "@mui/styles": "5.11.1", diff --git a/src/qqq/components/forms/EntityForm.tsx b/src/qqq/components/forms/EntityForm.tsx index bd01e2a..6e1f87e 100644 --- a/src/qqq/components/forms/EntityForm.tsx +++ b/src/qqq/components/forms/EntityForm.tsx @@ -44,9 +44,9 @@ import MDTypography from "qqq/components/legacy/MDTypography"; import HelpContent from "qqq/components/misc/HelpContent"; import QRecordSidebar from "qqq/components/misc/RecordSidebar"; import DynamicFormWidget from "qqq/components/widgets/misc/DynamicFormWidget"; +import FilterAndColumnsSetupWidget from "qqq/components/widgets/misc/FilterAndColumnsSetupWidget"; import PivotTableSetupWidget from "qqq/components/widgets/misc/PivotTableSetupWidget"; import RecordGridWidget, {ChildRecordListData} from "qqq/components/widgets/misc/RecordGridWidget"; -import ReportSetupWidget from "qqq/components/widgets/misc/ReportSetupWidget"; import {FieldRule, FieldRuleAction, FieldRuleTrigger} from "qqq/models/fields/FieldRules"; import HtmlUtils from "qqq/utils/HtmlUtils"; import Client from "qqq/utils/qqq/Client"; @@ -88,7 +88,7 @@ EntityForm.defaultProps = { //////////////////////////////////////////////////////////////////////////// let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: boolean): void => { -} +}; function EntityForm(props: Props): JSX.Element { @@ -119,11 +119,12 @@ function EntityForm(props: Props): JSX.Element const [, forceUpdate] = useReducer((x) => x + 1, 0); const [showEditChildForm, setShowEditChildForm] = useState(null as any); + const [modalDataChangedCounter, setModalDataChangedCount] = useState(0); const [notAllowedError, setNotAllowedError] = useState(null as string); const [formValuesJSON, setFormValuesJSON] = useState(""); - const [formValues, setFormValues] = useState({} as {[name: string]: any}); + const [formValues, setFormValues] = useState({} as { [name: string]: any }); const {pageHeader, setPageHeader} = useContext(QContext); @@ -282,6 +283,8 @@ function EntityForm(props: Props): JSX.Element setRenderedWidgetSections(newRenderedWidgetSections); forceUpdate(); + setModalDataChangedCount(modalDataChangedCounter + 1); + setShowEditChildForm(null); } @@ -291,7 +294,7 @@ function EntityForm(props: Props): JSX.Element *******************************************************************************/ useEffect(() => { - const newRenderedWidgetSections: {[name: string]: JSX.Element} = {}; + const newRenderedWidgetSections: { [name: string]: JSX.Element } = {}; for (let widgetName in renderedWidgetSections) { const widgetMetaData = metaData.widgets.get(widgetName); @@ -351,12 +354,11 @@ 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}) + function setFormFieldValuesFromWidget(values: { [name: string]: any }) { for (let key in values) { @@ -370,13 +372,13 @@ function EntityForm(props: Props): JSX.Element *******************************************************************************/ function getWidgetSection(widgetMetaData: QWidgetMetaData, widgetData: any): JSX.Element { - if(widgetMetaData.type == "childRecordList") + if (widgetMetaData.type == "childRecordList") { widgetData.viewAllLink = null; widgetMetaData.showExportButton = false; return ; } - if(widgetMetaData.type == "reportSetup") + if (widgetMetaData.type == "filterAndColumnsSetup") { - return + />; } - if(widgetMetaData.type == "pivotTableSetup") + if (widgetMetaData.type == "pivotTableSetup") { return + />; } - if(widgetMetaData.type == "dynamicForm") + if (widgetMetaData.type == "dynamicForm") { return + />; } - return (Unsupported widget type: {widgetMetaData.type}) + return (Unsupported widget type: {widgetMetaData.type}); } @@ -449,12 +460,12 @@ function EntityForm(props: Props): JSX.Element function setupFieldRules(tableMetaData: QTableMetaData) { const mdbMetaData = tableMetaData?.supplementalTableMetaData?.get("materialDashboard"); - if(!mdbMetaData) + if (!mdbMetaData) { return; } - if(mdbMetaData.fieldRules) + if (mdbMetaData.fieldRules) { const newFieldRules: FieldRule[] = []; for (let i = 0; i < mdbMetaData.fieldRules.length; i++) @@ -488,15 +499,15 @@ function EntityForm(props: Props): JSX.Element ///////////////////////////////////////////////// const tableSections = TableUtils.getSectionsForRecordSidebar(tableMetaData, [...tableMetaData.fields.keys()], (section: QTableSection) => { - const widget = metaData.widgets.get(section.widgetName); - if(widget) + const widget = metaData?.widgets.get(section.widgetName); + if (widget) { - if(widget.type == "childRecordList" && widget.defaultValues?.has("manageAssociationName")) + if (widget.type == "childRecordList" && widget.defaultValues?.has("manageAssociationName")) { return (true); } - if(widget.type == "reportSetup" || widget.type == "pivotTableSetup" || widget.type == "dynamicForm") + if (widget.type == "filterAndColumnsSetup" || widget.type == "pivotTableSetup" || widget.type == "dynamicForm") { return (true); } @@ -680,7 +691,7 @@ function EntityForm(props: Props): JSX.Element } const hasFields = section.fieldNames && section.fieldNames.length > 0; - if(hasFields) + if (hasFields) { for (let j = 0; j < section.fieldNames.length; j++) { @@ -719,7 +730,7 @@ function EntityForm(props: Props): JSX.Element } else { - const widgetMetaData = metaData.widgets.get(section.widgetName); + const widgetMetaData = metaData?.widgets.get(section.widgetName); const widgetData = await qController.widget(widgetMetaData.name, makeQueryStringWithIdAndObject(tableMetaData, defaultValues)); newRenderedWidgetSections[section.widgetName] = getWidgetSection(widgetMetaData, widgetData); @@ -1000,19 +1011,19 @@ function EntityForm(props: Props): JSX.Element /******************************************************************************* ** *******************************************************************************/ - function makeQueryStringWithIdAndObject(tableMetaData: QTableMetaData, object: {[key: string]: any}) + function makeQueryStringWithIdAndObject(tableMetaData: QTableMetaData, object: { [key: string]: any }) { const queryParamsArray: string[] = []; - if(props.id) + if (props.id) { - queryParamsArray.push(`${tableMetaData.primaryKeyField}=${encodeURIComponent(props.id)}`) + queryParamsArray.push(`${tableMetaData.primaryKeyField}=${encodeURIComponent(props.id)}`); } - if(object) + if (object) { for (let key in object) { - queryParamsArray.push(`${key}=${encodeURIComponent(object[key])}`) + queryParamsArray.push(`${key}=${encodeURIComponent(object[key])}`); } } @@ -1023,7 +1034,7 @@ function EntityForm(props: Props): JSX.Element /******************************************************************************* ** *******************************************************************************/ - async function reloadWidget(widgetName: string, additionalQueryParamsForWidget: {[key: string]: any }) + async function reloadWidget(widgetName: string, additionalQueryParamsForWidget: { [key: string]: any }) { const widgetData = await qController.widget(widgetName, makeQueryStringWithIdAndObject(tableMetaData, additionalQueryParamsForWidget)); const widgetMetaData = metaData.widgets.get(widgetName); @@ -1045,11 +1056,11 @@ function EntityForm(props: Props): JSX.Element /******************************************************************************* ** process a form-field having a changed value (e.g., apply field rules). *******************************************************************************/ - function handleChangedFieldValue(fieldName: string, oldValue: any, newValue: any, valueChangesToMake: {[fieldName: string]: any}) + function handleChangedFieldValue(fieldName: string, oldValue: any, newValue: any, valueChangesToMake: { [fieldName: string]: any }) { for (let fieldRule of fieldRules) { - if(fieldRule.trigger == FieldRuleTrigger.ON_CHANGE && fieldRule.sourceField == fieldName) + if (fieldRule.trigger == FieldRuleTrigger.ON_CHANGE && fieldRule.sourceField == fieldName) { switch (fieldRule.action) { @@ -1058,7 +1069,7 @@ function EntityForm(props: Props): JSX.Element valueChangesToMake[fieldRule.targetField] = null; break; case FieldRuleAction.RELOAD_WIDGET: - const additionalQueryParamsForWidget: {[key: string]: any} = {}; + const additionalQueryParamsForWidget: { [key: string]: any } = {}; additionalQueryParamsForWidget[fieldRule.sourceField] = newValue; reloadWidget(fieldRule.targetWidget, additionalQueryParamsForWidget); } @@ -1148,21 +1159,21 @@ function EntityForm(props: Props): JSX.Element ///////////////////////////////////////////////// // if we have values from formik, look at them // ///////////////////////////////////////////////// - if(values) + if (values) { //////////////////////////////////////////////////////////////////////// // use stringified values as cheap/easy way to see if any are changed // //////////////////////////////////////////////////////////////////////// const newFormValuesJSON = JSON.stringify(values); - if(formValuesJSON != newFormValuesJSON) + if (formValuesJSON != newFormValuesJSON) { - const valueChangesToMake: {[fieldName: string]: any} = {}; + const valueChangesToMake: { [fieldName: string]: any } = {}; //////////////////////////////////////////////////////////////////// // if the form is dirty (e.g., we're not doing the initial load), // // then process rules for any changed fields // //////////////////////////////////////////////////////////////////// - if(dirty) + if (dirty) { for (let fieldName in values) { @@ -1194,7 +1205,7 @@ function EntityForm(props: Props): JSX.Element setFieldValue(fieldName, valueChangesToMake[fieldName], false); } - setFormValues(formValues) + setFormValues(formValues); setFormValuesJSON(JSON.stringify(values)); } } diff --git a/src/qqq/components/misc/SavedViews.tsx b/src/qqq/components/misc/SavedViews.tsx index 32c7c6c..3b50094 100644 --- a/src/qqq/components/misc/SavedViews.tsx +++ b/src/qqq/components/misc/SavedViews.tsx @@ -25,7 +25,8 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QT import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobComplete"; import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError"; import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord"; -import {Alert, Box, Button} from "@mui/material"; +import {Alert, Button} from "@mui/material"; +import Box from "@mui/material/Box"; import Dialog from "@mui/material/Dialog"; import DialogActions from "@mui/material/DialogActions"; import DialogContent from "@mui/material/DialogContent"; @@ -94,12 +95,12 @@ function SavedViews({qController, metaData, tableMetaData, currentSavedView, tab const {accentColor, accentColorLight, userId: currentUserId} = useContext(QContext); - ///////////////////////////////////////////////////////////////////////////////////////// - // this component is used by - but that component has different usages - // - // e.g., the full-fledged query screen, but also, within other screens (e.g., a modal // - // under the ReportSetupWidget). So, there are some behaviors we only want when we're // - // on the full-fledged query screen, such as changing the URL with saved view ids. // - ///////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////// + // this component is used by - but that component has different usages - // + // e.g., the full-fledged query screen, but also, within other screens (e.g., a modal // + // under the FilterAndColumnsSetupWidget). So, there are some behaviors we only want when // + // we're on the full-fledged query screen, such as changing the URL with saved view ids. // + ///////////////////////////////////////////////////////////////////////////////////////////// const isQueryScreen = queryScreenUsage == "queryScreen"; const openSavedViewsMenu = (event: any) => setSavedViewsMenu(event.currentTarget); diff --git a/src/qqq/components/widgets/DashboardWidgets.tsx b/src/qqq/components/widgets/DashboardWidgets.tsx index ee57e83..edcf070 100644 --- a/src/qqq/components/widgets/DashboardWidgets.tsx +++ b/src/qqq/components/widgets/DashboardWidgets.tsx @@ -40,10 +40,10 @@ import DataBagViewer from "qqq/components/widgets/misc/DataBagViewer"; import DividerWidget from "qqq/components/widgets/misc/Divider"; import DynamicFormWidget from "qqq/components/widgets/misc/DynamicFormWidget"; import FieldValueListWidget from "qqq/components/widgets/misc/FieldValueListWidget"; +import FilterAndColumnsSetupWidget from "qqq/components/widgets/misc/FilterAndColumnsSetupWidget"; import PivotTableSetupWidget from "qqq/components/widgets/misc/PivotTableSetupWidget"; import QuickSightChart from "qqq/components/widgets/misc/QuickSightChart"; import RecordGridWidget from "qqq/components/widgets/misc/RecordGridWidget"; -import ReportSetupWidget from "qqq/components/widgets/misc/ReportSetupWidget"; import ScriptViewer from "qqq/components/widgets/misc/ScriptViewer"; import StepperCard from "qqq/components/widgets/misc/StepperCard"; import USMapWidget from "qqq/components/widgets/misc/USMapWidget"; @@ -598,9 +598,9 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco ) } { - widgetMetaData.type === "reportSetup" && ( + widgetMetaData.type === "filterAndColumnsSetup" && ( widgetData && widgetData[i] && widgetData[i].queryParams && - + { }} /> ) diff --git a/src/qqq/components/widgets/misc/ReportSetupWidget.tsx b/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx similarity index 72% rename from src/qqq/components/widgets/misc/ReportSetupWidget.tsx rename to src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx index 05ebfa2..eb15c5e 100644 --- a/src/qqq/components/widgets/misc/ReportSetupWidget.tsx +++ b/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx @@ -22,6 +22,9 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData"; import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData"; +import {QCriteriaOperator} from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator"; +import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterCriteria"; +import {QFilterOrderBy} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterOrderBy"; import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter"; import {Alert, Collapse} from "@mui/material"; import Box from "@mui/material/Box"; @@ -42,7 +45,7 @@ import Client from "qqq/utils/qqq/Client"; import FilterUtils from "qqq/utils/qqq/FilterUtils"; import React, {useContext, useEffect, useRef, useState} from "react"; -interface ReportSetupWidgetProps +interface FilterAndColumnsSetupWidgetProps { isEditable: boolean; widgetMetaData: QWidgetMetaData; @@ -50,7 +53,7 @@ interface ReportSetupWidgetProps onSaveCallback?: (values: { [name: string]: any }) => void; } -ReportSetupWidget.defaultProps = { +FilterAndColumnsSetupWidget.defaultProps = { onSaveCallback: null }; @@ -80,9 +83,10 @@ const qController = Client.getInstance(); /******************************************************************************* ** Component for editing the main setup of a report - that is: filter & columns *******************************************************************************/ -export default function ReportSetupWidget({isEditable, widgetMetaData, recordValues, onSaveCallback}: ReportSetupWidgetProps): JSX.Element +export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, recordValues, onSaveCallback}: FilterAndColumnsSetupWidgetProps): JSX.Element { const [modalOpen, setModalOpen] = useState(false); + const [hideColumns, setHideColumns] = useState(widgetMetaData?.defaultValues?.has("hideColumns") && widgetMetaData?.defaultValues?.get("hideColumns")); const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData); const [alertContent, setAlertContent] = useState(null as string); @@ -101,15 +105,36 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal ///////////////////////////// // load values from record // ///////////////////////////// - let queryFilter = recordValues["queryFilterJson"] && JSON.parse(recordValues["queryFilterJson"]) as QQueryFilter; + let columns: QQueryColumns = null; let usingDefaultEmptyFilter = false; + let queryFilter = recordValues["queryFilterJson"] && JSON.parse(recordValues["queryFilterJson"]) as QQueryFilter; if (!queryFilter) { queryFilter = new QQueryFilter(); - usingDefaultEmptyFilter = true; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // if there is no queryFilter provided, see if there are default fields from which a query should be seeded // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const defaultFilterFields = getDefaultFilterFieldNames(widgetMetaData); + if (defaultFilterFields?.length > 0) + { + defaultFilterFields.forEach((fieldName: string) => + { + if (recordValues[fieldName]) + { + queryFilter.addCriteria(new QFilterCriteria(fieldName, QCriteriaOperator.EQUALS, [recordValues[fieldName]])); + } + }); + + queryFilter.addOrderBy(new QFilterOrderBy("id", false)); + queryFilter = Object.assign({}, queryFilter); + } + else + { + usingDefaultEmptyFilter = true; + } } - let columns: QQueryColumns = null; if (recordValues["columnsJson"]) { columns = QQueryColumns.buildFromJSON(recordValues["columnsJson"]); @@ -120,11 +145,20 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal ////////////////////////////////////////////////////////////////////// useEffect(() => { - if (recordValues["tableName"] && (tableMetaData == null || tableMetaData.name != recordValues["tableName"])) + //////////////////////////////////////////////////////////////////////////////////////// + // if a default table name specified, use it, otherwise use it from the record values // + //////////////////////////////////////////////////////////////////////////////////////// + let tableName = widgetMetaData?.defaultValues?.get("tableName"); + if (!tableName && recordValues["tableName"] && (tableMetaData == null || tableMetaData.name != recordValues["tableName"])) + { + tableName = recordValues["tableName"]; + } + + if (tableName) { (async () => { - const tableMetaData = await qController.loadTableMetaData(recordValues["tableName"]); + const tableMetaData = await qController.loadTableMetaData(tableName); setTableMetaData(tableMetaData); const queryFilterForFrontend = Object.assign({}, queryFilter); @@ -132,7 +166,21 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal setFrontendQueryFilter(queryFilterForFrontend); })(); } - }, [recordValues]); + }, [JSON.stringify(recordValues)]); + + + /******************************************************************************* + ** + *******************************************************************************/ + function getDefaultFilterFieldNames(widgetMetaData: QWidgetMetaData) + { + if (widgetMetaData?.defaultValues?.has("filterDefaultFieldNames")) + { + return (widgetMetaData.defaultValues.get("filterDefaultFieldNames").split(",")); + } + + return ([]); + } /******************************************************************************* @@ -140,8 +188,27 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal *******************************************************************************/ function openEditor() { + let missingRequiredFields = [] as string[]; + getDefaultFilterFieldNames(widgetMetaData)?.forEach((fieldName: string) => + { + if (!recordValues[fieldName]) + { + missingRequiredFields.push(tableMetaData.fields.get(fieldName).label); + } + }); + + //////////////////////////////////////////////////////////////////// + // display an alert and return if any required fields are missing // + //////////////////////////////////////////////////////////////////// + if (missingRequiredFields.length > 0) + { + setAlertContent("The following fields must first be selected to add Additional Order Filters: '" + missingRequiredFields.join(", ") + "'"); + return; + } + if (recordValues["tableName"]) { + setAlertContent(null); setModalOpen(true); } } @@ -272,7 +339,14 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal const labelAdditionalElementsRight: JSX.Element[] = []; if (isEditable) { - labelAdditionalElementsRight.push(); + if (!hideColumns) + { + labelAdditionalElementsRight.push(); + } + else + { + labelAdditionalElementsRight.push(); + } } @@ -311,29 +385,31 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal } - -
Columns
- - { - mayShowColumnsPreview() && - columns.columns.map((column, i) => {renderColumn(column)}) - } - { - !mayShowColumnsPreview() && - - { - isEditable && - - - - } - { - !isEditable && Your report has no columns. - } - - } + {!hideColumns && ( + +
Columns
+ + { + mayShowColumnsPreview() && + columns.columns.map((column, i) => {renderColumn(column)}) + } + { + !mayShowColumnsPreview() && + + { + isEditable && + + + + } + { + !isEditable && Your report has no columns. + } + + } +
-
+ )} { modalOpen && closeEditor(event, reason)}> diff --git a/src/qqq/components/widgets/misc/PivotTableSetupWidget.tsx b/src/qqq/components/widgets/misc/PivotTableSetupWidget.tsx index 9c22a98..ebfc4bb 100644 --- a/src/qqq/components/widgets/misc/PivotTableSetupWidget.tsx +++ b/src/qqq/components/widgets/misc/PivotTableSetupWidget.tsx @@ -39,9 +39,9 @@ import colors from "qqq/assets/theme/base/colors"; import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons"; import FieldAutoComplete from "qqq/components/misc/FieldAutoComplete"; import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent"; +import {buttonSX, unborderedButtonSX} from "qqq/components/widgets/misc/FilterAndColumnsSetupWidget"; import {PivotTableGroupByElement} from "qqq/components/widgets/misc/PivotTableGroupByElement"; import {PivotTableValueElement} from "qqq/components/widgets/misc/PivotTableValueElement"; -import {buttonSX, unborderedButtonSX} from "qqq/components/widgets/misc/ReportSetupWidget"; import Widget, {HeaderToggleComponent} from "qqq/components/widgets/Widget"; import {PivotObjectKey, PivotTableDefinition, PivotTableFunction, pivotTableFunctionLabels, PivotTableGroupBy, PivotTableValue} from "qqq/models/misc/PivotTableDefinitionModels"; import QQueryColumns from "qqq/models/query/QQueryColumns"; diff --git a/src/qqq/pages/processes/ProcessRun.tsx b/src/qqq/pages/processes/ProcessRun.tsx index c99d816..dc04e26 100644 --- a/src/qqq/pages/processes/ProcessRun.tsx +++ b/src/qqq/pages/processes/ProcessRun.tsx @@ -94,7 +94,7 @@ const BACKOFF_AMOUNT = 1.5; //////////////////////////////////////////////////////////////////////////// let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: boolean): void => { -} +}; function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, isReport, recordIds, closeModalHandler, forceReInit, overrideLabel}: Props): JSX.Element { @@ -134,7 +134,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is const [showErrorDetail, setShowErrorDetail] = useState(false); const [showFullHelpText, setShowFullHelpText] = useState(false); - const [renderedWidgets, setRenderedWidgets] = useState({} as {[step: string]: {[widgetName: string]: any}}); + const [renderedWidgets, setRenderedWidgets] = useState({} as { [step: string]: { [widgetName: string]: any } }); const {pageHeader, recordAnalytics, setPageHeader, helpHelpActive} = useContext(QContext); @@ -238,15 +238,15 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is setShowFullHelpText(!showFullHelpText); }; - const download = (processValues: {[key: string]: string}) => + const download = (processValues: { [key: string]: string }) => { let url; let fileName = processValues.downloadFileName; - if(processValues.serverFilePath) + if (processValues.serverFilePath) { url = `/download/${encodeURIComponent(processValues.downloadFileName)}?filePath=${encodeURIComponent(processValues.serverFilePath)}`; } - else if(processValues.storageTableName && processValues.storageReference) + else if (processValues.storageTableName && processValues.storageReference) { url = `/download/${encodeURIComponent(processValues.downloadFileName)}?storageTableName=${encodeURIComponent(processValues.storageTableName)}&storageReference=${encodeURIComponent(processValues.storageReference)}`; } @@ -291,19 +291,19 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is *******************************************************************************/ function renderWidget(widgetName: string) { - if(!renderedWidgets[activeStep.name]) + if (!renderedWidgets[activeStep.name]) { renderedWidgets[activeStep.name] = {}; setRenderedWidgets(renderedWidgets); } - if(renderedWidgets[activeStep.name][widgetName]) + if (renderedWidgets[activeStep.name][widgetName]) { return renderedWidgets[activeStep.name][widgetName]; } const widgetMetaData = qInstance.widgets.get(widgetName); - if(!widgetMetaData) + if (!widgetMetaData) { return (Unrecognized widget name: {widgetName}); } @@ -311,12 +311,12 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is const queryStringParts: string[] = []; for (let name in processValues) { - queryStringParts.push(`${name}=${encodeURIComponent(processValues[name])}`) + queryStringParts.push(`${name}=${encodeURIComponent(processValues[name])}`); } const renderedWidget = ( - ) +
); renderedWidgets[activeStep.name][widgetName] = renderedWidget; return renderedWidget; } @@ -367,8 +367,8 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is - {isModal ? - : !isWidget && + {isModal ? handleCancelClicked(true)} disabled={false} label="Close" /> + : !isWidget && handleCancelClicked(true)} disabled={false} /> } @@ -500,7 +500,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is // edit the formData object to just include those. // ////////////////////////////////////////////////////////////////////////// let formDataToUse = formData; - if(component.values && component.values.includeFieldNames) + if (component.values && component.values.includeFieldNames) { formDataToUse = Object.assign({}, formData); @@ -608,21 +608,21 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is } { component.type === QComponentType.EDIT_FORM && - <> - { - component.values?.sectionLabel ? - - - - {component.values?.sectionLabel} - - - - - - : - } - + <> + { + component.values?.sectionLabel ? + + + + {component.values?.sectionLabel} + + + + + + : + } + } { component.type === QComponentType.VIEW_FORM && step.viewFields && ( @@ -1079,14 +1079,14 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is setProcessValues(qJobComplete.values); setQJobRunning(null); - if(formikSetFieldValueFunction) + if (formikSetFieldValueFunction) { ////////////////////////////////// // reset field values in formik // ////////////////////////////////// for (let key in qJobComplete.values) { - if(Object.hasOwn(formFields, key)) + if (Object.hasOwn(formFields, key)) { console.log(`(re)setting form field [${key}] to [${qJobComplete.values[key]}]`); formikSetFieldValueFunction(key, qJobComplete.values[key]); @@ -1098,7 +1098,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is // if the process step sent a new frontend-step-list, then refresh what we have in state (constructing new full model objects) // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const updatedFrontendStepList = qJobComplete.updatedFrontendStepList; - if(updatedFrontendStepList) + if (updatedFrontendStepList) { setSteps(updatedFrontendStepList); } @@ -1401,8 +1401,20 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is }); }; - const handleCancelClicked = () => + + /******************************************************************************* + ** + *******************************************************************************/ + const handleCancelClicked = (isClose: boolean) => { + ////////////////////////////////////////////////////////////////// + // unless this is a 'close', then tell backend we're cancelling // + ////////////////////////////////////////////////////////////////// + if (!isClose) + { + Client.getInstance().processCancel(processName, processUUID); + } + if (isModal && closeModalHandler) { closeModalHandler(null, "cancelClicked"); @@ -1415,6 +1427,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is navigate(path, {replace: true}); }; + const mainCardStyles: any = {}; const formStyles: any = {}; mainCardStyles.minHeight = `calc(100vh - ${isModal ? 150 : 400}px)`; @@ -1490,8 +1503,8 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is {/*************************************************************************** - ** step content - e.g., the appropriate form or other screen for the step ** - ***************************************************************************/} + ** step content - e.g., the appropriate form or other screen for the step ** + ***************************************************************************/} {getDynamicStepContent( activeStepIndex, activeStep, @@ -1507,8 +1520,8 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is setFieldValue, )} {/******************************** - ** back &| next/submit buttons ** - ********************************/} + ** back &| next/submit buttons ** + ********************************/} {true || activeStepIndex === 0 ? ( @@ -1526,7 +1539,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is )} { noMoreSteps && handleCancelClicked(true)} label={isModal ? "Close" : "Return"} iconName={isModal ? "cancel" : "arrow_back"} disabled={isSubmitting} /> @@ -1537,7 +1550,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is { !isWidget && ( - + handleCancelClicked(false)} disabled={isSubmitting} /> ) } @@ -1552,7 +1565,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is - ) + ); }} ); diff --git a/src/test/resources/fixtures/metaData/index.json b/src/test/resources/fixtures/metaData/index.json index 401fcda..54cd334 100644 --- a/src/test/resources/fixtures/metaData/index.json +++ b/src/test/resources/fixtures/metaData/index.json @@ -822,7 +822,7 @@ "reportSetupWidget": { "name": "reportSetupWidget", "label": "Filters and Columns", - "type": "reportSetup", + "type": "filterAndColumnsSetup", "isCard": true, "storeDropdownSelections": false, "showReloadButton": true,