feat(FlowEditor): allow adding new connection in step

This commit is contained in:
Ali BARIN
2022-10-15 19:13:28 +02:00
parent d83db08b81
commit ace2436e43
4 changed files with 66 additions and 8 deletions

View File

@@ -19,7 +19,7 @@ const generateDocsLink = (link: string) => (str: string) => (
); );
type AddAppConnectionProps = { type AddAppConnectionProps = {
onClose: () => void; onClose: (response: Record<string, unknown>) => void;
application: IApp; application: IApp;
connectionId?: string; connectionId?: string;
}; };
@@ -76,7 +76,7 @@ export default function AddAppConnection(props: AddAppConnectionProps): React.Re
stepIndex++; stepIndex++;
if (stepIndex === steps.length) { if (stepIndex === steps.length) {
onClose(); onClose(response);
} }
} }

View File

@@ -6,13 +6,16 @@ import Collapse from '@mui/material/Collapse';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
import Autocomplete from '@mui/material/Autocomplete'; import Autocomplete from '@mui/material/Autocomplete';
import type { IApp, IConnection, IStep, ISubstep } from '@automatisch/types';
import useFormatMessage from 'hooks/useFormatMessage';
import { EditorContext } from 'contexts/Editor'; import { EditorContext } from 'contexts/Editor';
import FlowSubstepTitle from 'components/FlowSubstepTitle'; import FlowSubstepTitle from 'components/FlowSubstepTitle';
import type { IApp, IConnection, IStep, ISubstep } from '@automatisch/types'; import AddAppConnection from 'components/AddAppConnection';
import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections'; import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections';
import { TEST_CONNECTION } from 'graphql/queries/test-connection'; import { TEST_CONNECTION } from 'graphql/queries/test-connection';
type ChooseConnectionSubstepProps = { type ChooseConnectionSubstepProps = {
application: IApp;
substep: ISubstep, substep: ISubstep,
expanded?: boolean; expanded?: boolean;
onExpand: () => void; onExpand: () => void;
@@ -22,6 +25,8 @@ type ChooseConnectionSubstepProps = {
step: IStep; step: IStep;
}; };
const ADD_CONNECTION_VALUE = 'ADD_CONNECTION';
const optionGenerator = (connection: IConnection): { label: string; value: string; } => ({ const optionGenerator = (connection: IConnection): { label: string; value: string; } => ({
label: connection?.formattedData?.screenName as string ?? 'Unnamed', label: connection?.formattedData?.screenName as string ?? 'Unnamed',
value: connection?.id as string, value: connection?.id as string,
@@ -38,13 +43,16 @@ function ChooseConnectionSubstep(props: ChooseConnectionSubstepProps): React.Rea
step, step,
onSubmit, onSubmit,
onChange, onChange,
application,
} = props; } = props;
const { const {
connection, connection,
appKey, appKey,
} = step; } = step;
const formatMessage = useFormatMessage();
const editorContext = React.useContext(EditorContext); const editorContext = React.useContext(EditorContext);
const { data, loading } = useQuery(GET_APP_CONNECTIONS, { variables: { key: appKey }}); const [showAddConnectionDialog, setShowAddConnectionDialog] = React.useState(false);
const { data, loading, refetch } = useQuery(GET_APP_CONNECTIONS, { variables: { key: appKey }});
// TODO: show detailed error when connection test/verification fails // TODO: show detailed error when connection test/verification fails
const [ const [
testConnection, testConnection,
@@ -72,10 +80,41 @@ function ChooseConnectionSubstep(props: ChooseConnectionSubstepProps): React.Rea
// intentionally no dependencies for initial test // intentionally no dependencies for initial test
}, []); }, []);
const connectionOptions = React.useMemo(() => (data?.getApp as IApp)?.connections?.map((connection) => optionGenerator(connection)) || [], [data]); const connectionOptions = React.useMemo(() => {
const appWithConnections = data?.getApp as IApp;
const options = appWithConnections
?.connections
?.map((connection) => optionGenerator(connection)) || [];
options.push({
label: formatMessage('chooseConnectionSubstep.addNewConnection'),
value: ADD_CONNECTION_VALUE
})
return options;
}, [data, formatMessage]);
const { name } = substep; const { name } = substep;
const handleAddConnectionClose = React.useCallback(async (response) => {
setShowAddConnectionDialog(false);
const connectionId = response?.createConnection.id;
if (connectionId) {
await refetch();
onChange({
step: {
...step,
connection: {
id: connectionId,
},
},
});
}
}, [onChange, refetch, step]);
const handleChange = React.useCallback((event: React.SyntheticEvent, selectedOption: unknown) => { const handleChange = React.useCallback((event: React.SyntheticEvent, selectedOption: unknown) => {
if (typeof selectedOption === 'object') { if (typeof selectedOption === 'object') {
// TODO: try to simplify type casting below. // TODO: try to simplify type casting below.
@@ -83,6 +122,11 @@ function ChooseConnectionSubstep(props: ChooseConnectionSubstepProps): React.Rea
const option: { value: string } = typedSelectedOption; const option: { value: string } = typedSelectedOption;
const connectionId = option?.value as string; const connectionId = option?.value as string;
if (connectionId === ADD_CONNECTION_VALUE) {
setShowAddConnectionDialog(true);
return;
}
if (connectionId !== step.connection?.id) { if (connectionId !== step.connection?.id) {
onChange({ onChange({
step: { step: {
@@ -122,7 +166,12 @@ function ChooseConnectionSubstep(props: ChooseConnectionSubstepProps): React.Rea
disableClearable disableClearable
disabled={editorContext.readOnly} disabled={editorContext.readOnly}
options={connectionOptions} options={connectionOptions}
renderInput={(params) => <TextField {...params} label="Choose connection" />} renderInput={(params) => (
<TextField
{...params}
label={formatMessage('chooseConnectionSubstep.chooseConnection')}
/>
)}
value={getOption(connectionOptions, connection?.id)} value={getOption(connectionOptions, connection?.id)}
onChange={handleChange} onChange={handleChange}
loading={loading} loading={loading}
@@ -136,10 +185,15 @@ function ChooseConnectionSubstep(props: ChooseConnectionSubstepProps): React.Rea
sx={{ mt: 2 }} sx={{ mt: 2 }}
disabled={testResultLoading || !connection?.verified || editorContext.readOnly}data-test="flow-substep-continue-button" disabled={testResultLoading || !connection?.verified || editorContext.readOnly}data-test="flow-substep-continue-button"
> >
Continue {formatMessage('chooseConnectionSubstep.continue')}
</Button> </Button>
</ListItem> </ListItem>
</Collapse> </Collapse>
{application && showAddConnectionDialog && <AddAppConnection
onClose={handleAddConnectionClose}
application={application}
/>}
</React.Fragment> </React.Fragment>
); );
} }

View File

@@ -251,7 +251,7 @@ export default function FlowStep(
index: number index: number
) => ( ) => (
<React.Fragment key={`${substep?.name}-${index}`}> <React.Fragment key={`${substep?.name}-${index}`}>
{substep.key === 'chooseConnection' && ( {substep.key === 'chooseConnection' && app && (
<ChooseConnectionSubstep <ChooseConnectionSubstep
expanded={currentSubstep === index + 1} expanded={currentSubstep === index + 1}
substep={substep} substep={substep}
@@ -259,6 +259,7 @@ export default function FlowStep(
onCollapse={() => toggleSubstep(index + 1)} onCollapse={() => toggleSubstep(index + 1)}
onSubmit={expandNextStep} onSubmit={expandNextStep}
onChange={handleChange} onChange={handleChange}
application={app}
step={step} step={step}
/> />
)} )}

View File

@@ -57,6 +57,9 @@
"flowEditor.pollIntervalValue": "Every {minutes} minutes", "flowEditor.pollIntervalValue": "Every {minutes} minutes",
"flowEditor.triggerEvent": "Trigger event", "flowEditor.triggerEvent": "Trigger event",
"flowEditor.actionEvent": "Action event", "flowEditor.actionEvent": "Action event",
"chooseConnectionSubstep.continue": "Continue",
"chooseConnectionSubstep.addNewConnection": "Add new connection",
"chooseConnectionSubstep.chooseConnection": "Choose connection",
"flow.createdAt": "created {datetime}", "flow.createdAt": "created {datetime}",
"flow.updatedAt": "updated {datetime}", "flow.updatedAt": "updated {datetime}",
"flow.view": "View", "flow.view": "View",