Merge pull request #551 from automatisch/issue-536
Show continue upon successful test and toggle next step upon continuing
This commit is contained in:
@@ -3,7 +3,7 @@ import { useMutation } from '@apollo/client';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import type { IFlow } from '@automatisch/types';
|
import type { IFlow, IStep } from '@automatisch/types';
|
||||||
|
|
||||||
import { GET_FLOW } from 'graphql/queries/get-flow';
|
import { GET_FLOW } from 'graphql/queries/get-flow';
|
||||||
import { CREATE_STEP } from 'graphql/mutations/create-step';
|
import { CREATE_STEP } from 'graphql/mutations/create-step';
|
||||||
@@ -96,6 +96,12 @@ export default function Editor(props: EditorProps): React.ReactElement {
|
|||||||
[createStep, flow.id]
|
[createStep, flow.id]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const openNextStep = React.useCallback((nextStep: IStep) => {
|
||||||
|
return () => {
|
||||||
|
setCurrentStepId(nextStep?.id);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
display="flex"
|
display="flex"
|
||||||
@@ -106,7 +112,7 @@ export default function Editor(props: EditorProps): React.ReactElement {
|
|||||||
py={3}
|
py={3}
|
||||||
gap={1}
|
gap={1}
|
||||||
>
|
>
|
||||||
{flow?.steps?.map((step, index) => (
|
{flow?.steps?.map((step, index, steps) => (
|
||||||
<React.Fragment key={`${step}-${index}`}>
|
<React.Fragment key={`${step}-${index}`}>
|
||||||
<FlowStep
|
<FlowStep
|
||||||
key={step.id}
|
key={step.id}
|
||||||
@@ -116,6 +122,7 @@ export default function Editor(props: EditorProps): React.ReactElement {
|
|||||||
onOpen={() => setCurrentStepId(step.id)}
|
onOpen={() => setCurrentStepId(step.id)}
|
||||||
onClose={() => setCurrentStepId(null)}
|
onClose={() => setCurrentStepId(null)}
|
||||||
onChange={onStepChange}
|
onChange={onStepChange}
|
||||||
|
onContinue={openNextStep(steps[index + 1])}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconButton onClick={() => addStep(step.id)} color="primary" disabled={creationInProgress || flow.active}>
|
<IconButton onClick={() => addStep(step.id)} color="primary" disabled={creationInProgress || flow.active}>
|
||||||
|
@@ -42,6 +42,7 @@ type FlowStepProps = {
|
|||||||
onOpen?: () => void;
|
onOpen?: () => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
onChange: (step: IStep) => void;
|
onChange: (step: IStep) => void;
|
||||||
|
onContinue?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const validIcon = <CheckCircleIcon color="success" />;
|
const validIcon = <CheckCircleIcon color="success" />;
|
||||||
@@ -99,7 +100,7 @@ function generateValidationSchema(substeps: ISubstep[]) {
|
|||||||
export default function FlowStep(
|
export default function FlowStep(
|
||||||
props: FlowStepProps
|
props: FlowStepProps
|
||||||
): React.ReactElement | null {
|
): React.ReactElement | null {
|
||||||
const { collapsed, onChange } = props;
|
const { collapsed, onChange, onContinue } = props;
|
||||||
const editorContext = React.useContext(EditorContext);
|
const editorContext = React.useContext(EditorContext);
|
||||||
const contextButtonRef = React.useRef<HTMLButtonElement | null>(null);
|
const contextButtonRef = React.useRef<HTMLButtonElement | null>(null);
|
||||||
const step: IStep = props.step;
|
const step: IStep = props.step;
|
||||||
@@ -273,6 +274,7 @@ export default function FlowStep(
|
|||||||
onCollapse={() => toggleSubstep(index + 1)}
|
onCollapse={() => toggleSubstep(index + 1)}
|
||||||
onSubmit={expandNextStep}
|
onSubmit={expandNextStep}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onContinue={onContinue}
|
||||||
step={step}
|
step={step}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@@ -54,8 +54,6 @@ const PowerInput = (props: PowerInputProps) => {
|
|||||||
} = props;
|
} = props;
|
||||||
const priorStepsWithExecutions = React.useContext(StepExecutionsContext);
|
const priorStepsWithExecutions = React.useContext(StepExecutionsContext);
|
||||||
const editorRef = React.useRef<HTMLDivElement | null>(null);
|
const editorRef = React.useRef<HTMLDivElement | null>(null);
|
||||||
const [target, setTarget] = React.useState<Range | null>(null);
|
|
||||||
const [index, setIndex] = React.useState(0);
|
|
||||||
const renderElement = React.useCallback(props => <Element {...props} />, []);
|
const renderElement = React.useCallback(props => <Element {...props} />, []);
|
||||||
const [editor] = React.useState(() => customizeEditor(createEditor()));
|
const [editor] = React.useState(() => customizeEditor(createEditor()));
|
||||||
const [showVariableSuggestions, setShowVariableSuggestions] = React.useState(false);
|
const [showVariableSuggestions, setShowVariableSuggestions] = React.useState(false);
|
||||||
@@ -72,7 +70,7 @@ const PowerInput = (props: PowerInputProps) => {
|
|||||||
(variable: Pick<VariableElement, "name" | "value">) => {
|
(variable: Pick<VariableElement, "name" | "value">) => {
|
||||||
insertVariable(editor, variable, stepsWithVariables);
|
insertVariable(editor, variable, stepsWithVariables);
|
||||||
},
|
},
|
||||||
[index, stepsWithVariables]
|
[stepsWithVariables]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -21,6 +21,7 @@ type TestSubstepProps = {
|
|||||||
onCollapse: () => void;
|
onCollapse: () => void;
|
||||||
onChange?: ({ step }: { step: IStep }) => void;
|
onChange?: ({ step }: { step: IStep }) => void;
|
||||||
onSubmit?: () => void;
|
onSubmit?: () => void;
|
||||||
|
onContinue?: () => void;
|
||||||
step: IStep;
|
step: IStep;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
onExpand,
|
onExpand,
|
||||||
onCollapse,
|
onCollapse,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
onContinue,
|
||||||
step,
|
step,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@@ -39,6 +41,9 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
const [executeFlow, { data, error, loading, called, reset }] = useMutation(EXECUTE_FLOW, { context: { autoSnackbar: false }});
|
const [executeFlow, { data, error, loading, called, reset }] = useMutation(EXECUTE_FLOW, { context: { autoSnackbar: false }});
|
||||||
const response = data?.executeFlow?.data;
|
const response = data?.executeFlow?.data;
|
||||||
|
|
||||||
|
const isCompleted = !error && called && !loading;
|
||||||
|
const hasNoOutput = !response && isCompleted;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
} = substep;
|
} = substep;
|
||||||
@@ -50,14 +55,20 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
}, [expanded, reset])
|
}, [expanded, reset])
|
||||||
|
|
||||||
const handleSubmit = React.useCallback(() => {
|
const handleSubmit = React.useCallback(() => {
|
||||||
|
if (isCompleted) {
|
||||||
|
onContinue?.();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
executeFlow({
|
executeFlow({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
stepId: step.id,
|
stepId: step.id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}, [onSubmit, step.id]);
|
}, [onSubmit, onContinue, isCompleted, step.id]);
|
||||||
const onToggle = expanded ? onCollapse : onExpand;
|
const onToggle = expanded ? onCollapse : onExpand;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -73,7 +84,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
{error?.graphQLErrors.map((error) => (<>{error.message}<br /></>))}
|
{error?.graphQLErrors.map((error) => (<>{error.message}<br /></>))}
|
||||||
</Alert>}
|
</Alert>}
|
||||||
|
|
||||||
{called && !loading && !error && !response && (
|
{hasNoOutput && (
|
||||||
<Alert severity="warning" sx={{ mb: 1, width: '100%' }}>
|
<Alert severity="warning" sx={{ mb: 1, width: '100%' }}>
|
||||||
<AlertTitle sx={{ fontWeight: 700 }}>{formatMessage('flowEditor.noTestDataTitle')}</AlertTitle>
|
<AlertTitle sx={{ fontWeight: 700 }}>{formatMessage('flowEditor.noTestDataTitle')}</AlertTitle>
|
||||||
|
|
||||||
@@ -96,7 +107,8 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
disabled={editorContext.readOnly}
|
disabled={editorContext.readOnly}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
Test & Continue
|
{isCompleted && formatMessage('flowEditor.continue')}
|
||||||
|
{!isCompleted && formatMessage('flowEditor.testAndContinue')}
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
@@ -49,6 +49,8 @@
|
|||||||
"flowEditor.publishedFlowCannotBeUpdated": "To edit this flow, you must first unpublish it.",
|
"flowEditor.publishedFlowCannotBeUpdated": "To edit this flow, you must first unpublish it.",
|
||||||
"flowEditor.noTestDataTitle": "We couldn't find matching data",
|
"flowEditor.noTestDataTitle": "We couldn't find matching data",
|
||||||
"flowEditor.noTestDataMessage": "Create a sample in the associated service and test the step again.",
|
"flowEditor.noTestDataMessage": "Create a sample in the associated service and test the step again.",
|
||||||
|
"flowEditor.testAndContinue": "Test & Continue",
|
||||||
|
"flowEditor.continue": "Continue",
|
||||||
"flow.createdAt": "created {datetime}",
|
"flow.createdAt": "created {datetime}",
|
||||||
"flow.updatedAt": "updated {datetime}",
|
"flow.updatedAt": "updated {datetime}",
|
||||||
"flow.view": "View",
|
"flow.view": "View",
|
||||||
|
Reference in New Issue
Block a user