import { useLazyQuery, useQuery } from '@apollo/client'; import Autocomplete from '@mui/material/Autocomplete'; import Button from '@mui/material/Button'; import Collapse from '@mui/material/Collapse'; import ListItem from '@mui/material/ListItem'; import TextField from '@mui/material/TextField'; import * as React from 'react'; import AddAppConnection from 'components/AddAppConnection'; import AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee'; import FlowSubstepTitle from 'components/FlowSubstepTitle'; import useAppConfig from 'hooks/useAppConfig.ee'; import { EditorContext } from 'contexts/Editor'; import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections'; import { TEST_CONNECTION } from 'graphql/queries/test-connection'; import useAuthenticateApp from 'hooks/useAuthenticateApp.ee'; import useFormatMessage from 'hooks/useFormatMessage'; const ADD_CONNECTION_VALUE = 'ADD_CONNECTION'; const ADD_SHARED_CONNECTION_VALUE = 'ADD_SHARED_CONNECTION'; const optionGenerator = (connection) => ({ label: connection?.formattedData?.screenName ?? 'Unnamed', value: connection?.id, }); const getOption = (options, connectionId) => options.find((connection) => connection.value === connectionId) || null; function ChooseConnectionSubstep(props) { const { substep, expanded = false, onExpand, onCollapse, step, onSubmit, onChange, application, } = props; const { connection, appKey } = step; const formatMessage = useFormatMessage(); const editorContext = React.useContext(EditorContext); const { authenticate } = useAuthenticateApp({ appKey: application.key, useShared: true, }); const [showAddConnectionDialog, setShowAddConnectionDialog] = React.useState(false); const [showAddSharedConnectionDialog, setShowAddSharedConnectionDialog] = React.useState(false); const { data, loading, refetch } = useQuery(GET_APP_CONNECTIONS, { variables: { key: appKey }, }); const { appConfig } = useAppConfig(application.key); // TODO: show detailed error when connection test/verification fails const [ testConnection, { loading: testResultLoading, refetch: retestConnection }, ] = useLazyQuery(TEST_CONNECTION, { variables: { id: connection?.id, }, }); React.useEffect(() => { if (connection?.id) { testConnection({ variables: { id: connection.id, }, }); } // intentionally no dependencies for initial test }, []); const connectionOptions = React.useMemo(() => { const appWithConnections = data?.getApp; const options = appWithConnections?.connections?.map((connection) => optionGenerator(connection), ) || []; if (!appConfig || appConfig.canCustomConnect) { options.push({ label: formatMessage('chooseConnectionSubstep.addNewConnection'), value: ADD_CONNECTION_VALUE, }); } if (appConfig?.canConnect) { options.push({ label: formatMessage('chooseConnectionSubstep.addNewSharedConnection'), value: ADD_SHARED_CONNECTION_VALUE, }); } return options; }, [data, formatMessage, appConfig]); const handleClientClick = async (appAuthClientId) => { try { const response = await authenticate?.({ appAuthClientId, }); const connectionId = response?.createConnection.id; if (connectionId) { await refetch(); onChange({ step: { ...step, connection: { id: connectionId, }, }, }); } } catch (err) { // void } finally { setShowAddSharedConnectionDialog(false); } }; 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, selectedOption) => { if (typeof selectedOption === 'object') { // TODO: try to simplify type casting below. const typedSelectedOption = selectedOption; const option = typedSelectedOption; const connectionId = option?.value; if (connectionId === ADD_CONNECTION_VALUE) { setShowAddConnectionDialog(true); return; } if (connectionId === ADD_SHARED_CONNECTION_VALUE) { setShowAddSharedConnectionDialog(true); return; } if (connectionId !== step.connection?.id) { onChange({ step: { ...step, connection: { id: connectionId, }, }, }); } } }, [step, onChange], ); React.useEffect(() => { if (step.connection?.id) { retestConnection({ id: step.connection.id, }); } }, [step.connection?.id, retestConnection]); const onToggle = expanded ? onCollapse : onExpand; return ( ( )} value={getOption(connectionOptions, connection?.id)} onChange={handleChange} loading={loading} data-test="choose-connection-autocomplete" /> {application && showAddConnectionDialog && ( )} {application && showAddSharedConnectionDialog && ( setShowAddSharedConnectionDialog(false)} onClientClick={handleClientClick} /> )} ); } export default ChooseConnectionSubstep;