Skip to content

Commit

Permalink
Merge branch 'master' into More_on_this_should_be_aligned_with_the_ic…
Browse files Browse the repository at this point in the history
…on_on_side_bar
  • Loading branch information
MahtabBukhari authored Jul 18, 2024
2 parents 0171b2d + 97a7c1b commit af7368a
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 42 deletions.
9 changes: 5 additions & 4 deletions src/components/App/SideBar/AiSummary/AiAnswer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import styled from 'styled-components'
import { highlightAiSummary } from '~/components/App/SideBar/AiSummary/utils/AiSummaryHighlight'
import { Flex } from '~/components/common/Flex'
import { Text } from '~/components/common/Text'
import { useDataStore, useFilteredNodes } from '~/stores/useDataStore'
import { useDataStore } from '~/stores/useDataStore'
import { useUserStore } from '~/stores/useUserStore'
import { ExtractedEntity } from '~/types/index'

type Props = {
answer: string
entities?: ExtractedEntity[]
hasBeenRendered: boolean
handleLoaded: () => void
}
Expand All @@ -25,11 +27,10 @@ const SummaryText = styled(Text)`
line-height: 19.6px;
`

export const AiAnswer = ({ answer, handleLoaded, hasBeenRendered }: Props) => {
export const AiAnswer = ({ answer, entities, handleLoaded, hasBeenRendered }: Props) => {
const { fetchData, setAbortRequests } = useDataStore((s) => s)
const { setBudget } = useUserStore((s) => s)
const [displayedText, setDisplayedText] = useState('')
const filteredNodes = useFilteredNodes()

useEffect(() => {
let timeoutId: NodeJS.Timeout
Expand Down Expand Up @@ -64,7 +65,7 @@ export const AiAnswer = ({ answer, handleLoaded, hasBeenRendered }: Props) => {
fetchData(setBudget, setAbortRequests, search)
}

const responseTextDisplay = highlightAiSummary(displayedText, filteredNodes, handleSubmit)
const responseTextDisplay = highlightAiSummary(displayedText, handleSubmit, entities)

return (
<Wrapper>
Expand Down
1 change: 1 addition & 0 deletions src/components/App/SideBar/AiSummary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const AiSummary = ({ question, response }: Props) => {
) : (
<AiAnswer
answer={response.answer || ''}
entities={response.entities}
handleLoaded={() => handleLoaded()}
hasBeenRendered={!!response?.hasBeenRendered}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import styled from 'styled-components'
import { NodeExtended } from '~/types'
import { Tooltip } from '~/components/common/ToolTip'
import { ExtractedEntity } from '~/types'
import { colors } from '~/utils'

export function highlightAiSummary(
sDescription: string,
nodesTerm: NodeExtended[] | null,
handleSubmit: (search: string) => void,
entities?: ExtractedEntity[],
) {
if (!nodesTerm || nodesTerm.length === 0) {
if (!entities || entities.length === 0) {
return sDescription
}

const sortedTerms = nodesTerm
.map((node) => node.name)
.filter((name) => typeof name === 'string')
const sortedEntities = entities
.map((entity) => entity.entity)
.filter((entity) => typeof entity === 'string')
.sort((a, b) => b.length - a.length)

const escapedTerms = sortedTerms.map((term) => escapeRegExp(term))
const escapedTerms = sortedEntities.map((entity) => escapeRegExp(entity))
const regex = new RegExp(`(${escapedTerms.join('|')})`, 'gi')

const parts = sDescription.split(regex)
Expand All @@ -25,18 +26,21 @@ export function highlightAiSummary(
return (
<>
{parts.map((part) => {
if (regex.test(part) && !highlighted.has(part.toLowerCase())) {
const entity = entities.find((e) => e.entity.toLowerCase() === part.toLowerCase())

if (entity && !highlighted.has(part.toLowerCase())) {
highlighted.add(part.toLowerCase())

return (
<Highlight
key={part}
onClick={() => {
handleSubmit(part)
}}
>
{part}
</Highlight>
<StyledTooltip key={part} content={entity.description}>
<Highlight
onClick={() => {
handleSubmit(part)
}}
>
{part}
</Highlight>
</StyledTooltip>
)
}

Expand All @@ -60,3 +64,24 @@ const Highlight = styled.span`
cursor: pointer;
}
`

const StyledTooltip = styled(({ className, ...props }) => (
<Tooltip
{...props}
backgroundColor={colors.BG2}
borderRadius="6px"
className={className}
color="white"
fontSize="12px"
fontWeight="500"
minWidth="160px"
padding="10px"
position="top"
textAlign="start"
whiteSpace="normal"
/>
))`
& .tooltip-content {
color: white;
}
`
23 changes: 21 additions & 2 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Leva } from 'leva'
import { lazy, Suspense, useCallback, useEffect } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { useSearchParams } from 'react-router-dom'
import 'react-toastify/dist/ReactToastify.css'
import { Socket } from 'socket.io-client'
import styled from 'styled-components'
Expand All @@ -18,7 +19,12 @@ import { useFeatureFlagStore } from '~/stores/useFeatureFlagStore'
import { useUpdateSelectedNode } from '~/stores/useGraphStore'
import { useTeachStore } from '~/stores/useTeachStore'
import { useUserStore } from '~/stores/useUserStore'
import { AiSummaryAnswerResponse, AiSummaryQuestionsResponse, AiSummarySourcesResponse } from '~/types'
import {
AiSummaryAnswerResponse,
AiSummaryQuestionsResponse,
AiSummarySourcesResponse,
ExtractedEntitiesResponse,
} from '~/types'
import { colors } from '~/utils/colors'
import { updateBudget } from '~/utils/setBudget'
import version from '~/utils/versionHelper'
Expand All @@ -29,7 +35,6 @@ import { DeviceCompatibilityNotice } from './DeviceCompatibilityNotification'
import { Helper } from './Helper'
import { SecondarySideBar } from './SecondarySidebar'
import { Toasts } from './Toasts'
import { useSearchParams } from 'react-router-dom'

const Wrapper = styled(Flex)`
height: 100%;
Expand Down Expand Up @@ -162,6 +167,15 @@ export const App = () => {
[addNewNode],
)

const handleExtractedEntities = useCallback(
(data: ExtractedEntitiesResponse) => {
if (data.question && getKeyExist(data.question)) {
setAiSummaryAnswer(data.question, { answerLoading: false, entities: data.entities })
}
},
[setAiSummaryAnswer, getKeyExist],
)

// setup socket
useEffect(() => {
if (socket) {
Expand All @@ -173,6 +187,10 @@ export const App = () => {

socket.on('newnode', handleNewNode)

if (chatInterfaceFeatureFlag) {
socket.on('extractedentitieshook', handleExtractedEntities)
}

// subscribe to ai_summary
if (chatInterfaceFeatureFlag) {
socket.on('askquestionhook', handleAiSummaryAnswer)
Expand Down Expand Up @@ -205,6 +223,7 @@ export const App = () => {
chatInterfaceFeatureFlag,
handleAiRelevantQuestions,
handleAiSources,
handleExtractedEntities,
])

return (
Expand Down
75 changes: 63 additions & 12 deletions src/components/common/ToolTip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ interface TooltipProps {
content: string
children: React.ReactNode
margin?: string
backgroundColor?: string
color?: string
padding?: string
fontSize?: string
fontWeight?: string
borderRadius?: string
position?: string
minWidth?: string
whiteSpace?: string
textAlign?: string
}

const TooltipContainer = styled.div`
Expand All @@ -12,37 +22,78 @@ const TooltipContainer = styled.div`
align-items: center;
`

const TooltipText = styled.div<{ margin?: string }>`
const TooltipText = styled.div<{
margin?: string
backgroundColor?: string
color?: string
padding?: string
fontSize?: string
fontWeight?: string
borderRadius?: string
position?: string
minWidth?: string
whiteSpace?: string
textAlign?: string
}>`
visibility: hidden;
width: auto;
background-color: white;
color: black;
text-align: center;
border-radius: 4px;
padding: 5px 8px;
background-color: ${({ backgroundColor }) => backgroundColor || 'white'};
color: ${({ color }) => color || 'black'};
text-align: ${({ textAlign }) => textAlign || 'center'};
min-width: ${({ minWidth }) => minWidth || 'auto'};
border-radius: ${({ borderRadius }) => borderRadius || '4px'};
padding: ${({ padding }) => padding || '5px 8px'};
position: absolute;
z-index: 1;
top: 100%;
${({ position }) => (position === 'top' ? 'bottom: 100%;' : 'top: 100%;')}
left: 50%;
transform: translateX(-50%);
margin-top: ${({ margin }) => margin || '0px'};
opacity: 0;
transition: opacity 0.3s;
white-space: nowrap;
white-space: ${({ whiteSpace }) => whiteSpace || 'nowrap'};
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
font-weight: 600;
font-size: ${({ fontSize }) => fontSize || '12px'};
font-weight: ${({ fontWeight }) => fontWeight || '600'};
${TooltipContainer}:hover & {
visibility: visible;
opacity: 1;
}
`

export const Tooltip = ({ content, children, margin }: TooltipProps) => (
export const Tooltip = ({
content,
children,
margin,
backgroundColor,
color,
padding,
fontSize,
fontWeight,
borderRadius,
minWidth,
whiteSpace,
position,
textAlign,
}: TooltipProps) => (
<TooltipContainer>
{children}
<TooltipText margin={margin}>{content}</TooltipText>
<TooltipText
backgroundColor={backgroundColor}
borderRadius={borderRadius}
color={color}
fontSize={fontSize}
fontWeight={fontWeight}
margin={margin}
minWidth={minWidth}
padding={padding}
position={position}
textAlign={textAlign}
whiteSpace={whiteSpace}
>
{content}
</TooltipText>
</TooltipContainer>
)
20 changes: 12 additions & 8 deletions src/network/fetchGraphData/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { isDevelopment, isE2E } from '~/constants'
import { api } from '~/network/api'
import { FetchDataResponse } from '~/types'
import { payLsat } from '~/utils'
import { getLSat } from '~/utils/getLSat'
import { payLsat } from '~/utils/payLsat'

// Main function to fetch graph data
export const fetchGraphData = async (
Expand All @@ -25,16 +25,20 @@ const fetchNodes = async (
const fetchWithLSAT = async (): Promise<FetchDataResponse> => {
const lsatToken = await getLSat()

const response = await api.get<FetchDataResponse>(url, { Authorization: lsatToken }, signal)
try {
const response = await api.get<FetchDataResponse>(url, { Authorization: lsatToken }, signal)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((response as any).status === 402) {
await payLsat(setBudget)
return response
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.status === 402) {
await payLsat(setBudget)

return fetchNodes(setBudget, params, signal, setAbortRequests)
}
return fetchNodes(setBudget, params, signal, setAbortRequests)
}

return response
throw error
}
}

if (!params.word || (isDevelopment && !isE2E)) {
Expand Down
12 changes: 12 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,16 @@ export type AIEntity = {
sourcesLoading?: boolean
questionsLoading?: boolean
hasBeenRendered?: boolean
entities?: ExtractedEntity[]
}

export interface ExtractedEntity {
entity: string
description: string
}

export interface ExtractedEntitiesResponse {
ref_id: string
question: string
entities: ExtractedEntity[]
}

0 comments on commit af7368a

Please sign in to comment.