Skip to content

Commit

Permalink
refactor(opentrons-ai-client): refactoring api call and inputprompt c…
Browse files Browse the repository at this point in the history
…omponent

refactoring api call and inputprompt component

close AUTH-402
  • Loading branch information
koji committed May 15, 2024
1 parent 476ee2c commit b1057e4
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 48 deletions.
123 changes: 75 additions & 48 deletions opentrons-ai-client/src/molecules/InputPrompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'
import { useForm } from 'react-hook-form'
import { useAtom } from 'jotai'
import axios from 'axios'
import { useAuth0 } from '@auth0/auth0-react'

import {
Expand All @@ -18,12 +17,13 @@ import {
} from '@opentrons/components'
import { SendButton } from '../../atoms/SendButton'
import { preparedPromptAtom, chatDataAtom } from '../../resources/atoms'
import { useApiCall } from '../../resources/hooks/useApiCall'
import { calcTextAreaHeight } from '../../resources/utils/utils'
import { END_POINT } from '../../resources/constants'

import type { AxiosRequestConfig } from 'axios'
import type { ChatData } from '../../resources/types'

const url =
'https://fk0py9eu3e.execute-api.us-east-2.amazonaws.com/sandbox/chat/completion'

interface InputType {
userPrompt: string
}
Expand All @@ -39,66 +39,93 @@ export function InputPrompt(): JSX.Element {
const [, setChatData] = useAtom(chatDataAtom)
const [submitted, setSubmitted] = React.useState<boolean>(false)

const [data, setData] = React.useState<any>(null)
const [loading, setLoading] = React.useState<boolean>(false)
// const [data, setData] = React.useState<any>(null)
// const [loading, setLoading] = React.useState<boolean>(false)

// ToDo (kk:05/15/2024) this will be used in the future
// const [error, setError] = React.useState<string>('')

const { getAccessTokenSilently } = useAuth0()

const userPrompt = watch('userPrompt') ?? ''

const calcTextAreaHeight = (): number => {
const rowsNum = userPrompt.split('\n').length
return rowsNum
}

// ToDo (kk:05/15/2024) This will be moved to a better place
const fetchData = async (prompt: string): Promise<void> => {
if (prompt !== '') {
setLoading(true)
try {
const accessToken = await getAccessTokenSilently({
authorizationParams: {
audience: 'sandbox-ai-api',
},
})
const postData = {
message: prompt,
fake: false,
}
const headers = {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
}
const response = await axios.post(url, postData, { headers })
setData(response.data)
} catch (err) {
// setError('Error fetching data from the API.')
console.error(`error: ${err}`)
} finally {
setLoading(false)
}
}
}

const handleClick = (): void => {
const { data, error, isLoading, fetchData } = useApiCall()

Check failure on line 52 in opentrons-ai-client/src/molecules/InputPrompt/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

'error' is assigned a value but never used

Check failure on line 52 in opentrons-ai-client/src/molecules/InputPrompt/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

'error' is assigned a value but never used

// // ToDo (kk:05/15/2024) This will be moved to a better place
// const fetchData = async (prompt: string): Promise<void> => {
// if (prompt !== '') {
// setLoading(true)
// try {
// const accessToken = await getAccessTokenSilently({
// authorizationParams: {
// audience: 'sandbox-ai-api',
// },
// })
// const postData = {
// message: prompt,
// fake: false,
// }
// const headers = {
// Authorization: `Bearer ${accessToken}`,
// 'Content-Type': 'application/json',
// }
// const response = await axios.post(END_POINT, postData, { headers })
// setData(response.data)
// } catch (err) {
// // setError('Error fetching data from the API.')
// console.error(`error: ${err}`)
// } finally {
// setLoading(false)
// }
// }
// }

const handleClick = async (): Promise<void> => {
const userInput: ChatData = {
role: 'user',
reply: userPrompt,
}
setChatData(chatData => [...chatData, userInput])
void fetchData(userPrompt)
setSubmitted(true)
reset()

try {
const accessToken = await getAccessTokenSilently({
authorizationParams: {
audience: 'sandbox-ai-api',
},
})

const headers = {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
}

const config = {
url: END_POINT,
method: 'POST',
headers,
data: {
message: userPrompt,
fake: false,
},
withCredentials: true,
}
console.log('called')
await fetchData(config as AxiosRequestConfig)
console.log('fetched')
console.log('data', data)
setSubmitted(true)
reset()
} catch (err) {
console.error(`error: ${err}`)
}
}

React.useEffect(() => {
if (preparedPrompt !== '') setValue('userPrompt', preparedPrompt as string)
}, [preparedPrompt, setValue])

React.useEffect(() => {
if (submitted && data != null && !loading) {
if (submitted && data != null && !isLoading) {
const { role, reply } = data
const assistantResponse: ChatData = {
role,
Expand All @@ -107,7 +134,7 @@ export function InputPrompt(): JSX.Element {
setChatData(chatData => [...chatData, assistantResponse])
setSubmitted(false)
}
}, [data, loading, submitted])
}, [data, isLoading, submitted])

// ToDo (kk:05/02/2024) This is also temp. Asking the design about error.
// console.error('error', error)
Expand All @@ -116,13 +143,13 @@ export function InputPrompt(): JSX.Element {
<StyledForm id="User_Prompt">
<Flex css={CONTAINER_STYLE}>
<StyledTextarea
rows={calcTextAreaHeight()}
rows={calcTextAreaHeight(userPrompt)}
placeholder={t('type_your_prompt')}
{...register('userPrompt')}
/>
<SendButton
disabled={userPrompt.length === 0}
isLoading={loading}
isLoading={isLoading}
handleClick={handleClick}
/>
</Flex>
Expand Down
2 changes: 2 additions & 0 deletions opentrons-ai-client/src/resources/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const END_POINT =
'https://fk0py9eu3e.execute-api.us-east-2.amazonaws.com/sandbox/chat/completion'
Empty file.
40 changes: 40 additions & 0 deletions opentrons-ai-client/src/resources/hooks/useApiCall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useState } from 'react'
import axios from 'axios'

import type { AxiosRequestConfig } from 'axios'

interface UseApiCallResult<T> {
data: T | null
error: string | null
isLoading: boolean
fetchData: (config: AxiosRequestConfig) => Promise<void>
}

export const useApiCall = <T>(): UseApiCallResult<T> => {
const [data, setData] = useState<T | null>(null)
const [error, setError] = useState<string | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(false)

const fetchData = async (config: AxiosRequestConfig): Promise<void> => {
console.log('useApiCall - fetchData')
setIsLoading(true)
setError(null)

try {
const response = await axios.request<T>({
...config,
withCredentials: true,
})
console.log(response)
setData(response.data)
} catch (err: any) {
// ToDo (kk:05/15/2024) remove any
console.log(err)
setError(err.message as string)
} finally {
setIsLoading(false)
}
}

return { data, error, isLoading, fetchData }
}
17 changes: 17 additions & 0 deletions opentrons-ai-client/src/resources/hooks/useGetAuth0Token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useAuth0 } from '@auth0/auth0-react'

const audience = 'sandbox-ai-api'
export const useGetAuth0Token = async (): Promise<string | null> => {
const { getAccessTokenSilently } = useAuth0()
try {
const accessToken = await getAccessTokenSilently({
authorizationParams: {
audience,
},
})
return accessToken
} catch (err) {
console.error(`cannot get token: ${err}`)
}
return null
}
11 changes: 11 additions & 0 deletions opentrons-ai-client/src/resources/utils/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { describe, it, expect } from 'vitest'
import { calcTextAreaHeight } from '../utils'

describe('calcTextAreaHeight', () => {
it('should return the correct number of lines', () => {
const input = 'Hello\nWorld\nThis is testing data.'
const expectedOutput = 3
const result = calcTextAreaHeight(input)
expect(result).toEqual(expectedOutput)
})
})
10 changes: 10 additions & 0 deletions opentrons-ai-client/src/resources/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Calculates the number of lines in a given string.
* @param input - The string to calculate the number of lines for.
* @returns The number of lines in the input string.
*/

export const calcTextAreaHeight = (input: string): number => {
const rowsNum = input.split('\n').length
return rowsNum
}

0 comments on commit b1057e4

Please sign in to comment.