import React, { Fragment, useContext, useEffect, useState } from 'react' import { RequestContext } from './Request.context'; import { IRequestDetailsComponentProps } from './request.model'; import PageLayout from '../../layouts/PageLayout'; import { BreadcrumbData } from '../../components/Breadcrumbs/Breadcrumbs'; import RequestDetailsService from '../../modules/request-details/services/request-details.service'; import { IActivityData, IIntent, IRequestData, IKLRequest, IMatchEntity, IFlowData, IDomainData, IServiceCatalog, IKBData } from '../../modules/request-details/models'; import ChatInfo from '../../modules/request-details/components/chat-info/ChatInfo'; import ChatMetadata from '../../modules/request-details/components/chat-metadata/ChatMetadata'; import './request-details.scss' import Activity from '../../modules/request-details/components/activity/Activity'; import AnnotationWorkbench from '../../modules/request-details/components/annotation-workbench/annotation-workbench/AnnotationWorkbench'; import AiseraLoader from '../../components/AiseraLoader/AiseraLoader'; import { IAnnotationWorkbenchItem } from '../../modules/request-details/components/annotation-workbench/workbench-accordion/WorkbenchAccordion'; import { LanguageCode } from '../../core/models/core.model'; import { EntityHighlighterService } from '../../modules/request-details/services/entity-highlight-service'; import { ISelectOption } from '@components/Select/Select'; import { AutocompleteOption } from '@components/Autocomplete/Autocomplete'; const RequestDetailsComponent = ({ ChatSimulatorView }: IRequestDetailsComponentProps) => { const { requestId, actions, botId, userId } = useContext(RequestContext); const [breadcrumb, setBreadcrumb] = useState([{ label: 'Home' }, { label: 'Request Table' }, { label: 'Request Details' }]); const [request, setRequest] = useState(); const [activities, setActivities] = useState([]); const [domains, setDomains] = useState([]); const [flows, setFlows] = useState([]); const [serviceCatalogs, setServiceCatalogs] = useState([]); const [kbArticles, setKBArticles] = useState([]); const [conversationFeedback, setConversationFeedback] = useState() const [channelToken, setChannelToken] = useState(''); const [annotationWorkbenchItems, setAnnotationWorkbenchItems] = useState([]); const [annotatedPhrases, setAnnotatedPhrases] = useState([]); const [currentClickedPhrase, setCurrentClickedPhrase] = useState() const [isWorkbenchLoading, setIsWorkbenchLoading] = useState(false); useEffect(() => { const fetchRequest = async () => { const requestData = await RequestDetailsService.fetchRequestInfo(requestId); const intents = requestData?.intents?.map((a: IIntent) => a.id); if (intents?.length) { const intentsData = await RequestDetailsService.fetchIntents(intents); requestData._intentsCategories = intentsData as string[]; } else { requestData._intentsCategories = "None"; } setRequestEntitiesToHighlight(requestData); if(requestData.session_id) { const requestCountInSession = await RequestDetailsService.fetchRequestCountInSession(requestData.session_id); requestData.totalRequestsInSession = requestCountInSession.totalCount; } else { requestData.totalRequestsInSession = 1; } setRequest(requestData); setBreadcrumb(currentBreadCrumbData => { currentBreadCrumbData[currentBreadCrumbData.length - 1] = { label: requestData.title }; return [...currentBreadCrumbData]; }); }; fetchRequest(); const fetchActivities = async () => { const activitiesData = await RequestDetailsService.fetchActivities(requestId); setActivities(activitiesData); }; fetchActivities(); const fetchFlows = async () => { const flowsData = await RequestDetailsService.fetchFlows(botId); const flowsDataList = flowsData.map((flow: IFlowData) => ({ label: flow.name, value: flow.name, key: flow.name, id: flow.db_id })) setFlows(flowsDataList); }; // fetchFlows(); const fetchServiceCatalogs = async () => { const scData = await RequestDetailsService.fetchServiceCatalogs(botId); const scDataList = scData.map((sc: IServiceCatalog) => ({ label: sc.title, value: sc.title, key: sc.title, id: sc.id })) setServiceCatalogs(scDataList); }; // fetchServiceCatalogs(); const fetchKBArticles = async () => { const kbData = await RequestDetailsService.fetchKBArticles(botId); const kbDataList = kbData.map((kb: IKBData) => ({ label: kb.title, value: kb.title, key: kb.title, id: kb.id })) setKBArticles(kbDataList); }; // fetchKBArticles(); const fetchDomains = async () => { const domainsData = await RequestDetailsService.fetchDomains(); const domainsDataList = domainsData.map((domain: IDomainData) => ({ label: domain.name, value: domain.name, _isPurchased: domain._isPurchased })) setDomains(domainsDataList); }; fetchDomains(); const fetchFulfillment = async () => { const fulfillmentData = await RequestDetailsService.fetchFulfillment(requestId); const flowsDataList = fulfillmentData.map((flow: IFlowData) => ({ label: flow.name, value: flow.name, id: flow.id })) setFlows(flowsDataList); }; // fetchFulfillment(); const fetchConversationFeedback = async () => { const feedbackData = await RequestDetailsService.fetchConversationFeedback(requestId); console.log(feedbackData) setConversationFeedback(feedbackData); }; fetchConversationFeedback(); // const updateConversationFeedback = async () => { // const res = await RequestDetailsService.updateConversationFeedback(userId); // return; // }; // updateConversationFeedback(); // const createConversationFeedback = async () => { // const res = await RequestDetailsService.createConversationFeedback(userId, requestId); // return; // }; // createConversationFeedback(); }, []); useEffect(() => { if(request) { processRequestTitleAsAnnotationWorkbench(request); } },[request]) useEffect(() => { if (request && !annotatedPhrases?.length) { setAnnotatedPhrases([request.title]); setCurrentClickedPhrase(request.title); } }, [request]); useEffect(() => { if (annotatedPhrases.length) { // addPhraseToAnnotationWorkbench(annotatedPhrases); } }, [annotatedPhrases]); useEffect(() => { if(activities?.length) { const queries: string[] = []; for (const act of activities) { const phrases = act.chats?.filter(({questionType}) => questionType === 'UserInput')?.map(({question}) => question); if(phrases?.length) { for (const phrase of phrases) { if(!queries.includes(phrase)) { queries.push(phrase); } } } } setAnnotatedPhrases(queries); setCurrentClickedPhrase(queries[0]); } }, [activities]); const setRequestEntitiesToHighlight = ({_historicalEvents}: IRequestData) => { setEntitiesToHighlight(_historicalEvents?.entities as IMatchEntity[]); } const setEntitiesToHighlight = (entities: IMatchEntity[]) => { entities?.forEach(({id}) => EntityHighlighterService.setEntity(id)); } const getNewlyAddedPhrase = () => { if (!annotationWorkbenchItems.length) { return annotatedPhrases[0]; } const existedInAnnotatedItems = annotationWorkbenchItems.map(item => item.label); const notExisted = annotatedPhrases.find(phrase => !existedInAnnotatedItems.includes(phrase)); return notExisted; } const handleBreadCrumbClick = (breadcrumbItem: BreadcrumbData) => { const index = breadcrumb.indexOf(breadcrumbItem); if (index !== - 1) { actions.handler({ type: 'BreadcrumbNavigation', data: { index: breadcrumb.indexOf(breadcrumbItem) } }); } } const spellCheckStatus = (spellCheckInfos: string[]) => { if (!spellCheckInfos) { return false; } if (spellCheckInfos.length < 4) { return false; } if (spellCheckInfos[1] === spellCheckInfos[3]) { return false; } return { source: spellCheckInfos[1].split("text: ").pop(), sink: spellCheckInfos[3].split("text: ").pop(), }; } const getRequestFulfillmentsToRender = (fulfillmentSources: string[]) => { if(!fulfillmentSources || !fulfillmentSources.length) { return 'None'; } return Array.from(new Set(fulfillmentSources)).join(', '); } const processRequestTitleAsAnnotationWorkbench = async (request: IRequestData) => { setIsWorkbenchLoading(true); const label = request?.title; const currentMatchesData = await RequestDetailsService.fetchCurrentMatch(requestId); if(!currentMatchesData) { setIsWorkbenchLoading(false); return; } const languageDetection = LanguageCode[(request.session?.language_detected?.code) as keyof typeof LanguageCode]; const entities = currentMatchesData?.entities?.map(({ score, entityName, id }) => ({ score, entityName, id })) || []; const intents = currentMatchesData?.intents?.map(({ score, name, id, utterance }) => ({ score, name, id, matchedPhrase: utterance.text })) || []; const fulfillments = currentMatchesData?.fulfillments?.map(({ score, name, id, type, source }) => ({ score, name, id, type, source })) || []; const fufillmentSource = getRequestFulfillmentsToRender(request?.requestFulfillments?.map(({producer}) => producer)) setEntitiesToHighlight(entities); const annotationItem = { label, languageDetection, entities, intents, fulfillments, fufillmentSource, }; setAnnotationWorkbenchItems([annotationItem]); setIsWorkbenchLoading(false); } const processKlRequest = async (response: IKLRequest): Promise => { const entities = response?.debugInfoV2?.conversation?.entities.map(({ score, entityName, id }) => ({ score, entityName, id })) || []; const intents = response?.debugInfoV2?.conversation?.intents.map(({ score, name, id }) => ({ score, name, id, matchedPhrase: '' })) || []; const fulfillments = response?.debugInfoV2?.conversation?.fulfillments?.map(({ score, name, id, type, source }) => ({ score, name, id, type, source })) || []; setEntitiesToHighlight(entities); let domainUnderstanding = 'None'; let spellCheck = spellCheckStatus(response?.debugInfoV2?.icm?.content?.debugInfo?.logs?.['02_SpellChecker']); const fulSource = new Set(fulfillments.map(({ source }) => source)); let fufillmentSource = Array.from(fulSource)?.join(', ') || 'None'; const intentIds = intents.map(({ id }) => id); if (intentIds.length) { const matchedInfo = await RequestDetailsService.fetchMatchedInfo(intentIds); if (matchedInfo.length) { domainUnderstanding = matchedInfo.map(({ domain }) => domain).join(','); } const utterences = {} as any; response?.debugInfoV2?.icm?.content?.debugInfo?.intents?.reduce((utterences: any, intent: any) => utterences[intent?.id] = intent?.utterance?.text, utterences); intents.forEach(intent => intent.matchedPhrase = utterences[intent.id]); } const label = response?.debugInfoV2?.request; const languageDetection = LanguageCode[(response?.responseLanguage) as keyof typeof LanguageCode] return { entities, intents, fulfillments, languageDetection, label, domainUnderstanding, spellCheck, fufillmentSource } as IAnnotationWorkbenchItem; } const addPhraseToAnnotationWorkbench = async (phrases: string[]) => { setIsWorkbenchLoading(true); let token = channelToken if (!token) { token = await RequestDetailsService.fetchChannelToken(botId); setChannelToken(token); } const processedResponses = []; for (const phrase of phrases) { const klRequest = await RequestDetailsService.fetchCurrentMatchForPhrase(phrase, token, botId, userId); const processedResponse = await processKlRequest(klRequest); // processedResponses.push(processedResponse); setAnnotationWorkbenchItems((prev) => [...prev, processedResponse]); } // setAnnotationWorkbenchItems(processedResponses); setIsWorkbenchLoading(false); } const addToAnnotationWorkbench = (phrase: string) => { setCurrentClickedPhrase(phrase); } return ( { request && (
Historical Activity ({activities.length})
{ request?.conversation?.error_message && (
An error happened in this conversation: {request?.conversation?.error_message}
) || null } { activities?.length && request ? (activities.map((activity, index) => ( ))) : null }
) || }
) } export default RequestDetailsComponent;