diff --git a/package.json b/package.json index 7d60d4209..a16ecc302 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "@types/webpack-env": "^1.13.1", "@types/webpack-hot-middleware": "^2.15.0", "@typescript-eslint/parser": "^1.0.0", - "@xstate/react": "^0.8.1", + "@xstate/react": "^1.0.0", "add-asset-html-webpack-plugin": "^2.1.3", "autoprefixer": "^8.3.0", "axios": "^0.18.1", diff --git a/src/components/Launch/LaunchWorkflowForm/LaunchWorkflowForm.tsx b/src/components/Launch/LaunchWorkflowForm/LaunchWorkflowForm.tsx index a89b89d50..d1368161e 100644 --- a/src/components/Launch/LaunchWorkflowForm/LaunchWorkflowForm.tsx +++ b/src/components/Launch/LaunchWorkflowForm/LaunchWorkflowForm.tsx @@ -6,82 +6,87 @@ import { FormHelperText, Typography } from '@material-ui/core'; -import { WaitForData } from 'components/common'; import { ButtonCircularProgress } from 'components/common/ButtonCircularProgress'; -import { APIContextValue, useAPIContext } from 'components/data/apiContext'; -import { isLoadingState } from 'components/hooks/fetchMachine'; -import { - FilterOperationName, - NamedEntityIdentifier, - SortDirection, - workflowSortFields -} from 'models'; import * as React from 'react'; import { formStrings } from './constants'; import { InputValueCacheContext } from './inputValueCache'; +import { LaunchState } from './launchMachine'; import { LaunchWorkflowFormInputs } from './LaunchWorkflowFormInputs'; import { SearchableSelector } from './SearchableSelector'; import { useStyles } from './styles'; import { LaunchWorkflowFormProps } from './types'; import { UnsupportedRequiredInputsError } from './UnsupportedRequiredInputsError'; import { useLaunchWorkflowFormState } from './useLaunchWorkflowFormState'; -import { workflowsToSearchableSelectorOptions } from './utils'; - -function generateFetchSearchResults( - { listWorkflows }: APIContextValue, - workflowId: NamedEntityIdentifier -) { - return async (query: string) => { - const { project, domain, name } = workflowId; - const { entities: workflows } = await listWorkflows( - { project, domain, name }, - { - filter: [ - { - key: 'version', - operation: FilterOperationName.CONTAINS, - value: query - } - ], - sort: { - key: workflowSortFields.createdAt, - direction: SortDirection.DESCENDING - } - } - ); - return workflowsToSearchableSelectorOptions(workflows); - }; -} /** Renders the form for initiating a Launch request based on a Workflow */ export const LaunchWorkflowForm: React.FC = props => { - const state = useLaunchWorkflowFormState(props); - const { submissionState, unsupportedRequiredInputs, workflows } = state; + const { + formKey, + formInputsRef, + showErrors, + inputValueCache, + onCancel, + onSubmit, + state, + workflowSourceSelectorState + } = useLaunchWorkflowFormState(props); const styles = useStyles(); - const fetchSearchResults = generateFetchSearchResults( - useAPIContext(), - props.workflowId - ); + + const { + fetchSearchResults, + launchPlanSelectorOptions, + onSelectLaunchPlan, + onSelectWorkflowVersion, + selectedLaunchPlan, + selectedWorkflow, + workflowSelectorOptions + } = workflowSourceSelectorState; const submit: React.FormEventHandler = event => { event.preventDefault(); - state.onSubmit(); + onSubmit(); }; - const submissionInFlight = isLoadingState(submissionState.state); - const preventSubmit = - submissionInFlight || - !state.inputsReady || - unsupportedRequiredInputs.length > 0; + const submissionInFlight = state.matches(LaunchState.SUBMITTING); + const canSubmit = [ + LaunchState.ENTER_INPUTS, + LaunchState.VALIDATING_INPUTS, + LaunchState.INVALID_INPUTS, + LaunchState.SUBMIT_FAILED + ].some(state.matches); + const showWorkflowSelector = ![ + LaunchState.LOADING_WORKFLOW_VERSIONS, + LaunchState.FAILED_LOADING_WORKFLOW_VERSIONS + ].some(state.matches); + const showLaunchPlanSelector = + state.context.workflowVersion && + ![ + LaunchState.LOADING_LAUNCH_PLANS, + LaunchState.FAILED_LOADING_LAUNCH_PLANS + ].some(state.matches); + const showInputs = [ + LaunchState.UNSUPPORTED_INPUTS, + LaunchState.ENTER_INPUTS, + LaunchState.VALIDATING_INPUTS, + LaunchState.INVALID_INPUTS, + LaunchState.SUBMIT_VALIDATING, + LaunchState.SUBMITTING, + LaunchState.SUBMIT_FAILED, + LaunchState.SUBMIT_SUCCEEDED + ].some(state.matches); + // TODO: We removed all loading indicators here. Decide if we want skeletons + // instead. return ( - +
{formStrings.title}
- {state.workflowName} + + {state.context.sourceWorkflowId?.name} +
- + {showWorkflowSelector ? (
= props => {
- -
- + +
+ ) : null} + {showInputs ? ( +
+ {state.matches(LaunchState.UNSUPPORTED_INPUTS) ? ( + + ) : ( + -
-
- {state.inputsReady ? ( -
- {state.unsupportedRequiredInputs.length > 0 ? ( - - ) : ( - - )} -
- ) : null} -
+ )} + + ) : null}
- {!!submissionState.lastError && ( + {state.matches(LaunchState.SUBMIT_FAILED) ? ( - {submissionState.lastError.message} + {state.context.error.message} - )} + ) : null}