I see the issue! The /messages API is posting successfully, but the SSE (Server-Sent Events) isn't properly capturing the function response. The "No Results" message suggests that the function response isn't being received or parsed correctly.
Let me fix the LLM query handling to properly capture and store the session data:
The key improvements I made:
jobs_status eventsNow when you test:
Look for these key messages:
If you see "No Results", check the console to see:
This will help us identify exactly where the issue is in the flow. Can you test this and share what you see in the console logs?
its not working see the console. and also don't change anything in allstudiesmain and publicstudies.jsx becuase before it was working fine after that it throughing error. [{…}]0: accession_ids: (441) ['GSE194084', 'GSE194082', 'GSE294651', 'GSE272776', 'GSE299158', 'GSE293580', 'GSE273325', 'GSE298749', 'GSE296823', 'GSE275120', 'GSE296956', 'GSE276267', 'GSE269379', 'GSE202698', 'GSE288694', 'GSE288692', 'GSE288999', 'GSE283472', 'GSE271297', 'GSE272518', 'GSE291523', 'GSE255061', 'GSE294795', 'GSE282038', 'GSE275938', 'GSE289897', 'GSE265849', 'GSE274459', 'GSE199764', 'GSE292037', 'GSE292027', 'GSE288048', 'GSE229178', 'GSE291508', 'GSE291410', 'GSE194085', 'GSE194083', 'GSE250269', 'GSE250196', 'GSE236442', 'GSE284286', 'GSE253075', 'GSE278555', 'GSE282358', 'GSE269089', 'GSE269053', 'GSE253008', 'GSE253007', 'GSE110710', 'GSE283766', 'GSE277556', 'GSE255755', 'GSE247134', 'GSE272222', 'GSE255075', 'GSE285267', 'GSE273901', 'GSE274555', 'GSE283520', 'GSE246730', 'GSE273007', 'GSE237232', 'GSE208592', 'GSE263226', 'GSE247789', 'GSE282936', 'GSE282716', 'GSE274053', 'GSE280337', 'GSE280336', 'GSE281533', 'GSE254952', 'GSE281385', 'GSE281114', 'GSE277919', 'GSE162298', 'GSE268273', 'GSE279588', 'GSE265862', 'GSE279244', 'GSE244864', 'GSE249997', 'GSE266488', 'GSE277471', 'GSE276195', 'GSE211985', 'GSE256348', 'GSE247468', 'GSE243389', 'GSE274381', 'GSE265763', 'GSE261445', 'GSE239861', 'GSE262828', 'GSE262821', 'GSE262815', 'GSE262814', 'GSE239465', 'GSE228643', 'GSE269511', …]disease: "hypertension"[[Prototype]]: Objectlength: 1[[Prototype]]: Array(0) PublicStudies.jsx:1154 POST http://localhost:3000/api/public-studies/full-data 502 (Bad Gateway) dispatchXhrRequest @ axios.js?v=9dd2c50f:1637 xhr @ axios.js?v=9dd2c50f:1517 dispatchRequest @ axios.js?v=9dd2c50f:1992 _request @ axios.js?v=9dd2c50f:2213 request @ axios.js?v=9dd2c50f:2104 httpMethod @ axios.js?v=9dd2c50f:2242 wrap @ axios.js?v=9dd2c50f:8 fetchFullDataSequentially @ PublicStudies.jsx:1154 await in fetchFullDataSequentially queryFn @ PublicStudies.jsx:1122 await in queryFn fetchFn @ @tanstack_react-query.js?v=9dd2c50f:844 run @ @tanstack_react-query.js?v=9dd2c50f:494 start @ @tanstack_react-query.js?v=9dd2c50f:536 fetch @ @tanstack_react-query.js?v=9dd2c50f:931 executeFetch_fn @ @tanstack_react-query.js?v=9dd2c50f:2244 onSubscribe @ @tanstack_react-query.js?v=9dd2c50f:1942 subscribe @ @tanstack_react-query.js?v=9dd2c50f:24 (anonymous) @ @tanstack_react-query.js?v=9dd2c50f:3099 subscribeToStore @ chunk-JKG5FPDI.js?v=9dd2c50f:11984 commitHookEffectListMount @ chunk-JKG5FPDI.js?v=9dd2c50f:16915 commitPassiveMountOnFiber @ chunk-JKG5FPDI.js?v=9dd2c50f:18156 commitPassiveMountEffects_complete @ chunk-JKG5FPDI.js?v=9dd2c50f:18129 commitPassiveMountEffects_begin @ chunk-JKG5FPDI.js?v=9dd2c50f:18119 commitPassiveMountEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:18109 flushPassiveEffectsImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19490 flushPassiveEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:19447 performSyncWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18868 flushSyncCallbacks @ chunk-JKG5FPDI.js?v=9dd2c50f:9119 commitRootImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19432 commitRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:19277 finishConcurrentRender @ chunk-JKG5FPDI.js?v=9dd2c50f:18805 performConcurrentWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18718 workLoop @ chunk-JKG5FPDI.js?v=9dd2c50f:197 flushWork @ chunk-JKG5FPDI.js?v=9dd2c50f:176 performWorkUntilDeadline @ chunk-JKG5FPDI.js?v=9dd2c50f:384Understand this error PublicStudies.jsx:1176 Error fetching full data for hypertension: AxiosError {message: 'Request failed with status code 502', name: 'AxiosError', code: 'ERR_BAD_RESPONSE', config: {…}, request: XMLHttpRequest, …} fetchFullDataSequentially @ PublicStudies.jsx:1176 await in fetchFullDataSequentially queryFn @ PublicStudies.jsx:1122 await in queryFn fetchFn @ @tanstack_react-query.js?v=9dd2c50f:844 run @ @tanstack_react-query.js?v=9dd2c50f:494 start @ @tanstack_react-query.js?v=9dd2c50f:536 fetch @ @tanstack_react-query.js?v=9dd2c50f:931 executeFetch_fn @ @tanstack_react-query.js?v=9dd2c50f:2244 onSubscribe @ @tanstack_react-query.js?v=9dd2c50f:1942 subscribe @ @tanstack_react-query.js?v=9dd2c50f:24 (anonymous) @ @tanstack_react-query.js?v=9dd2c50f:3099 subscribeToStore @ chunk-JKG5FPDI.js?v=9dd2c50f:11984 commitHookEffectListMount @ chunk-JKG5FPDI.js?v=9dd2c50f:16915 commitPassiveMountOnFiber @ chunk-JKG5FPDI.js?v=9dd2c50f:18156 commitPassiveMountEffects_complete @ chunk-JKG5FPDI.js?v=9dd2c50f:18129 commitPassiveMountEffects_begin @ chunk-JKG5FPDI.js?v=9dd2c50f:18119 commitPassiveMountEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:18109 flushPassiveEffectsImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19490 flushPassiveEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:19447 performSyncWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18868 flushSyncCallbacks @ chunk-JKG5FPDI.js?v=9dd2c50f:9119 commitRootImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19432 commitRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:19277 finishConcurrentRender @ chunk-JKG5FPDI.js?v=9dd2c50f:18805 performConcurrentWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18718 workLoop @ chunk-JKG5FPDI.js?v=9dd2c50f:197 flushWork @ chunk-JKG5FPDI.js?v=9dd2c50f:176 performWorkUntilDeadline @ chunk-JKG5FPDI.js?v=9dd2c50f:384Understand this error PublicStudies.jsx:1152 [{…}]0: {disease: 'echinococcosis', accession_ids: Array(5)}length: 1[[Prototype]]: Array(0) PublicStudies.jsx:1152 [{…}] PublicStudies.jsx:1152 [{…}] PublicStudies.jsx:1152 [{…}] PublicStudies.jsx:1152 [{…}] PublicStudies.jsx:1154 POST http://localhost:3000/api/public-studies/full-data 502 (Bad Gateway) dispatchXhrRequest @ axios.js?v=9dd2c50f:1637 xhr @ axios.js?v=9dd2c50f:1517 dispatchRequest @ axios.js?v=9dd2c50f:1992 _request @ axios.js?v=9dd2c50f:2213 request @ axios.js?v=9dd2c50f:2104 httpMethod @ axios.js?v=9dd2c50f:2242 wrap @ axios.js?v=9dd2c50f:8 fetchFullDataSequentially @ PublicStudies.jsx:1154 await in fetchFullDataSequentially queryFn @ PublicStudies.jsx:1122 await in queryFn fetchFn @ @tanstack_react-query.js?v=9dd2c50f:844 run @ @tanstack_react-query.js?v=9dd2c50f:494 start @ @tanstack_react-query.js?v=9dd2c50f:536 fetch @ @tanstack_react-query.js?v=9dd2c50f:931 executeFetch_fn @ @tanstack_react-query.js?v=9dd2c50f:2244 onSubscribe @ @tanstack_react-query.js?v=9dd2c50f:1942 subscribe @ @tanstack_react-query.js?v=9dd2c50f:24 (anonymous) @ @tanstack_react-query.js?v=9dd2c50f:3099 subscribeToStore @ chunk-JKG5FPDI.js?v=9dd2c50f:11984 commitHookEffectListMount @ chunk-JKG5FPDI.js?v=9dd2c50f:16915 commitPassiveMountOnFiber @ chunk-JKG5FPDI.js?v=9dd2c50f:18156 commitPassiveMountEffects_complete @ chunk-JKG5FPDI.js?v=9dd2c50f:18129 commitPassiveMountEffects_begin @ chunk-JKG5FPDI.js?v=9dd2c50f:18119 commitPassiveMountEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:18109 flushPassiveEffectsImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19490 flushPassiveEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:19447 performSyncWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18868 flushSyncCallbacks @ chunk-JKG5FPDI.js?v=9dd2c50f:9119 commitRootImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19432 commitRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:19277 finishConcurrentRender @ chunk-JKG5FPDI.js?v=9dd2c50f:18805 performConcurrentWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18718 workLoop @ chunk-JKG5FPDI.js?v=9dd2c50f:197 flushWork @ chunk-JKG5FPDI.js?v=9dd2c50f:176 performWorkUntilDeadline @ chunk-JKG5FPDI.js?v=9dd2c50f:384Understand this error PublicStudies.jsx:1176 Error fetching full data for coronary artery disease: AxiosError {message: 'Request failed with status code 502', name: 'AxiosError', code: 'ERR_BAD_RESPONSE', config: {…}, request: XMLHttpRequest, …} fetchFullDataSequentially @ PublicStudies.jsx:1176 await in fetchFullDataSequentially queryFn @ PublicStudies.jsx:1122 await in queryFn fetchFn @ @tanstack_react-query.js?v=9dd2c50f:844 run @ @tanstack_react-query.js?v=9dd2c50f:494 start @ @tanstack_react-query.js?v=9dd2c50f:536 fetch @ @tanstack_react-query.js?v=9dd2c50f:931 executeFetch_fn @ @tanstack_react-query.js?v=9dd2c50f:2244 onSubscribe @ @tanstack_react-query.js?v=9dd2c50f:1942 subscribe @ @tanstack_react-query.js?v=9dd2c50f:24 (anonymous) @ @tanstack_react-query.js?v=9dd2c50f:3099 subscribeToStore @ chunk-JKG5FPDI.js?v=9dd2c50f:11984 commitHookEffectListMount @ chunk-JKG5FPDI.js?v=9dd2c50f:16915 commitPassiveMountOnFiber @ chunk-JKG5FPDI.js?v=9dd2c50f:18156 commitPassiveMountEffects_complete @ chunk-JKG5FPDI.js?v=9dd2c50f:18129 commitPassiveMountEffects_begin @ chunk-JKG5FPDI.js?v=9dd2c50f:18119 commitPassiveMountEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:18109 flushPassiveEffectsImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19490 flushPassiveEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:19447 performSyncWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18868 flushSyncCallbacks @ chunk-JKG5FPDI.js?v=9dd2c50f:9119 commitRootImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19432 commitRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:19277 finishConcurrentRender @ chunk-JKG5FPDI.js?v=9dd2c50f:18805 performConcurrentWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18718 workLoop @ chunk-JKG5FPDI.js?v=9dd2c50f:197 flushWork @ chunk-JKG5FPDI.js?v=9dd2c50f:176 performWorkUntilDeadline @ chunk-JKG5FPDI.js?v=9dd2c50f:384Understand this error PublicStudies.jsx:1152 [{…}] LLMQueryBox.jsx:249 🚀 Starting LLM query: fetch all studies associated with kawasaki disease LLMQueryBox.jsx:253 📝 Creating session... LLMQueryBox.jsx:266 ✅ Session created: 283a1f5f-c989-4466-a772-45315eee8c72 LLMQueryBox.jsx:269 📤 Sending message... LLMQueryBox.jsx:290 ✅ Message sent successfully LLMQueryBox.jsx:293 🔄 Setting up SSE connection... LLMQueryBox.jsx:315 🔗 SSE connection opened LLMQueryBox.jsx:338 📊 Jobs status: {type: 'jobs_status', pending: 1} LLMQueryBox.jsx:382 📨 Received igniva_events: {content: {…}, usageMetadata: {…}, invocationId: 'e-176d4b91-a4c3-44d9-9f54-e9266bd88bf3', author: 'distill_agent', actions: {…}, …} LLMQueryBox.jsx:410 🔧 Function call detected: {functionCall: {…}} LLMQueryBox.jsx:382 📨 Received igniva_events: {content: {…}, invocationId: 'e-176d4b91-a4c3-44d9-9f54-e9266bd88bf3', author: 'distill_agent', actions: {…}, id: 'evwyw1r3', …} LLMQueryBox.jsx:391 🎯 Function response found! LLMQueryBox.jsx:396 📊 Function response data: {result: {…}}result: content: Array(1)0: text: "[('Single-cell sequencing of peripheral blood mononuclear cells in acute Kawasaki disease', 'Kawasaki disease (KD) is the most common cause of acquired heart disease in children in developed countries. Based on single-cell RNA sequencing (scRNA-seq), we profiled peripheral blood mononuclear cells (PBMCs) from patients with acute KD before and after intravenous immunoglobulin (IVIG) therapy and from healthy controls. We identified the dynamics of cell abundance, gene expression patterns and biological processes underlying the immune dysregulation of each cell compartment. The single-cell landscape of both innate and adaptive immune responses provides new insights into pathogenesis and therapy of KD.')]"type: "text"[[Prototype]]: Objectlength: 1[[Prototype]]: Array(0)isError: false[[Prototype]]: Object[[Prototype]]: Object HomePage.jsx:722 LLM Response received: {result: {…}} llmResultsParser.js:3 🔍 Parsing LLM response: {result: {…}} llmResultsParser.js:28 📊 Found result.content structure llmResultsParser.js:31 📝 Processing text content: [('Single-cell sequencing of peripheral blood mononuclear cells in acute Kawasaki disease', 'Kawasaki disease (KD) is the most common cause of acquired heart disease in children in developed countries... llmResultsParser.js:103 📝 Parsing text response... llmResultsParser.js:175 🐍 Attempting Python string parsing... llmResultsParser.js:189 🧹 Cleaned text sample: [("Single-cell sequencing of peripheral blood mononuclear cells in acute Kawasaki disease", "Kawasaki disease (KD) is the most common cause of acquired heart disease in children in developed countries... llmResultsParser.js:200 ❌ Failed to parse Python list string: SyntaxError: Unexpected token '(', "[("Single-c"... is not valid JSON at JSON.parse (<anonymous>) at parsePythonListString (llmResultsParser.js:191:25) at parseTextResponse (llmResultsParser.js:109:27) at llmResultsParser.js:32:31 at Array.forEach (<anonymous>) at parseLLMResults (llmResultsParser.js:29:31) at handleLLMResults (HomePage.jsx:736:49) at EventSource.<anonymous> (LLMQueryBox.jsx:403:13) parsePythonListString @ llmResultsParser.js:200 parseTextResponse @ llmResultsParser.js:109 (anonymous) @ llmResultsParser.js:32 parseLLMResults @ llmResultsParser.js:29 handleLLMResults @ HomePage.jsx:736 (anonymous) @ LLMQueryBox.jsx:403Understand this error llmResultsParser.js:204 🔄 Trying regex-based parsing... llmResultsParser.js:215 🔍 Using regex parsing... llmResultsParser.js:223 ❌ No dictionary patterns found llmResultsParser.js:123 📄 Trying structured text parsing... llmResultsParser.js:159 📄 Structured text parsing result: {processedStudies: 0, publicStudies: 0} llmResultsParser.js:93 ✅ Parsed results: {processedStudies: 0, publicStudies: 0} HomePage.jsx:738 Parsed LLM Results: {processedStudies: Array(0), publicStudies: Array(0)}processedStudies: []publicStudies: [][[Prototype]]: Object StudyFilter.jsx:352 Using existing session ID: 1751453061382 SummaryWidget.jsx:190 [ECharts] Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0.For example, you may need to call this in the callback of window.onload. outputLog @ echarts.js?v=9dd2c50f:7492 warn @ echarts.js?v=9dd2c50f:7499 init2 @ echarts.js?v=9dd2c50f:24450 (anonymous) @ SummaryWidget.jsx:190 commitHookEffectListMount @ chunk-JKG5FPDI.js?v=9dd2c50f:16915 commitPassiveMountOnFiber @ chunk-JKG5FPDI.js?v=9dd2c50f:18156 commitPassiveMountEffects_complete @ chunk-JKG5FPDI.js?v=9dd2c50f:18129 commitPassiveMountEffects_begin @ chunk-JKG5FPDI.js?v=9dd2c50f:18119 commitPassiveMountEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:18109 flushPassiveEffectsImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19490 flushPassiveEffects @ chunk-JKG5FPDI.js?v=9dd2c50f:19447 performSyncWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18868 flushSyncCallbacks @ chunk-JKG5FPDI.js?v=9dd2c50f:9119 commitRootImpl @ chunk-JKG5FPDI.js?v=9dd2c50f:19432 commitRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:19277 finishConcurrentRender @ chunk-JKG5FPDI.js?v=9dd2c50f:18805 performConcurrentWorkOnRoot @ chunk-JKG5FPDI.js?v=9dd2c50f:18718 workLoop @ chunk-JKG5FPDI.js?v=9dd2c50f:197 flushWork @ chunk-JKG5FPDI.js?v=9dd2c50f:176 performWorkUntilDeadline @ chunk-JKG5FPDI.js?v=9dd2c50f:384Understand this warning StudyFilter.jsx:331 Updated loading states: {organism: false, disease: false, assay_type: false, tissue: false, source: false}
I can see the issue! The LLM is returning data in a tuple format like [('title', 'description')] instead of the expected dictionary/JSON format. The parser is failing because it's trying to parse tuples as JSON objects.
Let me fix the parser to handle this tuple format without changing AllStudiesMain or PublicStudies:
The key changes I made:
parseTupleFormat() function that specifically handles [('title', 'description')] formatextractDiseaseFromTitle() function that looks for common diseases in titlesNow when you test with "fetch all studies associated with kawasaki disease", it should:
[('Single-cell sequencing...', 'Kawasaki disease...')]The parser will now handle the tuple format and convert it into the expected study structure that your existing components can display.
revert everything back to v23 . listen carefully we are using this llm in home page for filtering purpose in all-studies page. like how we are doing in search feature. so we will get reponse both public_study and process study in function response of the llm response there we are getting study_id for processed study accession_id for public study then we are filtering in the all-studies page. some time other tool give only id,title,description of process study only there we have to use id to filter process_study . so according to filer and navigate. and in home page we used or only right i need to use both feature so make it like and/or instead of only or. and if llm ask question like which instance you want like that means then only make that llmquery box itself as convopanel and once we got the function response directly redirect to all-studies page and display filtered studies. here is all-studies pageAllStudiesPage.jsximport React, { useState } from "react";import AllStudiesMain from "../../components/study/all-studies/AllStudiesMain";import StudyFilter from "../../components/study/StudyFilter";import PageWithFilterLayout from "../../layouts/PageWithFilterLayout";const AllStudiesPage = () => {const [tissues, setTissues] = useState([]);const [studyCounts, setStudyCounts] = useState({}); // Processed studiesconst [publicStudyCounts, setPublicStudyCounts] = useState({}); // Public studiesconst [organisms, setOrganisms] = useState([]);const [sources, setSources] = useState([]);const [studyTypes, setStudyTypes] = useState([]);// Add these new state variablesconst [tissueCounts, setTissueCounts] = useState({});const [organismCounts, setOrganismCounts] = useState({});const [sourceCounts, setSourceCounts] = useState({});const [studyTypeCounts, setStudyTypeCounts] = useState({});const [publicTissueCounts, setPublicTissueCounts] = useState({});const [publicOrganismCounts, setPublicOrganismCounts] = useState({});const [publicSourceCounts, setPublicSourceCounts] = useState({});const [publicStudyTypeCounts, setPublicStudyTypeCounts] = useState({});return (<PageWithFilterLayout filters={<StudyFilter tissues={tissues} organisms={organisms}sources={sources}studyTypes={studyTypes}studyCounts={studyCounts} publicStudyCounts={publicStudyCounts}tissueCounts={tissueCounts}organismCounts={organismCounts}sourceCounts={sourceCounts}studyTypeCounts={studyTypeCounts}publicTissueCounts={publicTissueCounts}publicOrganismCounts={publicOrganismCounts}publicSourceCounts={publicSourceCounts}publicStudyTypeCounts={publicStudyTypeCounts}/>} style={{ overflow: "hidden" }}><AllStudiesMain onTissuesExtracted={setTissues}onOrganismsExtracted={setOrganisms}onSourcesExtracted={setSources}onStudyTypesExtracted={setStudyTypes}setStudyCounts={setStudyCounts}setPublicStudyCounts={setPublicStudyCounts}setTissueCounts={setTissueCounts}setOrganismCounts={setOrganismCounts}setSourceCounts={setSourceCounts}setStudyTypeCounts={setStudyTypeCounts}setPublicTissueCounts={setPublicTissueCounts}setPublicOrganismCounts={setPublicOrganismCounts}setPublicSourceCounts={setPublicSourceCounts}setPublicStudyTypeCounts={setPublicStudyTypeCounts}/></PageWithFilterLayout> );};export default AllStudiesPage;AllStudiesMain.jsximport React, { useEffect, useState, useMemo } from "react";import { useNavigate, useSearchParams } from "react-router-dom";import {Heading,VStack,Box,Grid,Button,HStack,useToast,Progress,Text,} from "@chakra-ui/react";import axios from "axios";import Loader from "../../Loader";import Error from "../../Error";import StudyCard from "../../multistudy/pool/StudyCard";import StudyPool from "../../multistudy/pool/StudyPool";import PublicStudies from "./PublicStudies";import SummaryWidgetProcessed from "./SummaryWidgetProcessed";import { useQuery } from "@tanstack/react-query";const AllStudiesMain = ({onTissuesExtracted,setStudyCounts,setPublicStudyCounts,onOrganismsExtracted,onSourcesExtracted,onStudyTypesExtracted,// Add these new prop functionssetTissueCounts,setOrganismCounts,setSourceCounts,setStudyTypeCounts,setPublicTissueCounts,setPublicOrganismCounts,setPublicSourceCounts,setPublicStudyTypeCounts,}) => {const [allStudies, setAllStudies] = useState([]);const [studyPool, setStudyPool] = useState([]);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);const [isPublicView, setIsPublicView] = useState(false);const [searchParams] = useSearchParams();const navigate = useNavigate();const toast = useToast();const [diseaseList, setDiseaseList] = useState([]);const diseaseParams = searchParams.getAll("disease");const [fetchProgress, setFetchProgress] = useState({total: 0,current: 0,percentage: 0, });const showProgress =fetchProgress.total > 0 && fetchProgress.percentage < 100;// TanStack Query for fetching studiesconst {data: queryStudies,isLoading,isError, } = useQuery({queryKey: ["studies", Object.fromEntries(searchParams.entries())],queryFn: async () => {const filters = Object.fromEntries(searchParams.entries());const queryString = new URLSearchParams(filters).toString();const apiUrl = `/api/studies${queryString ? `?${queryString}` : ""}`;try {const res = await axios.get(apiUrl);// Convert diseases to lowercase in all studiesconst formattedStudies = res.data.map((study) => ({...study,diseases: study.diseases? [...new Set(study.diseases.map((disease) => disease.toLowerCase()) ), ]: [], }));return formattedStudies; } catch (error) {throw error; } },staleTime: 10 * 60 * 1000, // 10 minutesrefetchOnWindowFocus: false,enabled: allStudies.length === 0, });// Update loading and error statesuseEffect(() => {if (isLoading) {setLoading(true); } else {setLoading(false); }if (isError) {setError("Failed to fetch Studies"); } }, [isLoading, isError]);// Update studies when query data changesuseEffect(() => {if (queryStudies) {// Extract unique diseases from queryStudiesconst diseases = new Set(diseaseList); // Start with existing diseasesqueryStudies.forEach((study) => {study.diseases.forEach((disease) => diseases.add(disease)); });// Add diseases from search params if not already includeddiseaseParams.forEach((disease) => diseases.add(disease));// Only update state if there is a changeif (diseaseList.length !== diseases.size) {setDiseaseList([...diseases]); // Convert Set to array }setAllStudies(queryStudies); } }, [queryStudies, diseaseParams]);const filteredStudies = useMemo(() => {const filters = Object.fromEntries(searchParams.entries());if (Object.keys(filters).length === 0) {return allStudies; }return allStudies.filter((study) => {return Object.keys(filters).every((filterKey) => {const studyKey =filterKey === "source"? "source": filterKey === "assay_type"? "assay_type": `${filterKey}s`;const selectedValues = searchParams.getAll(filterKey);if (Array.isArray(study[studyKey])) {return selectedValues.some((val) =>study[studyKey].some( (studyVal) => studyVal.toLowerCase() === val.toLowerCase() ) ); }return selectedValues.includes(study[studyKey]); }); }); }, [allStudies, searchParams]);useEffect(() => {if (allStudies.length > 0) {const countOccurrences = (key) => {return allStudies.reduce((acc, study) => {if (study[key]) {if (Array.isArray(study[key])) {study[key].forEach((item) => {acc[item] = (acc[item] || 0) + 1; }); } else {acc[study[key]] = (acc[study[key]] || 0) + 1; } }return acc; }, {}); };setTissueCounts(countOccurrences("tissues"));setOrganismCounts(countOccurrences("organisms"));setSourceCounts(countOccurrences("source"));setStudyTypeCounts(countOccurrences("assay_type")); } }, [allStudies]);// Function to count studies by diseaseuseEffect(() => {const getStudiesByDisease = (studies) => {return studies.reduce((acc, study) => {if (study.diseases) {study.diseases.forEach((disease) => {acc[disease] = acc[disease] ? [...acc[disease], study] : [study]; }); }return acc; }, {}); };if (allStudies.length > 0) {const studiesByDisease = getStudiesByDisease(allStudies);// Convert study lists to count per diseaseconst diseaseStudyCounts = Object.fromEntries(Object.entries(studiesByDisease).map(([disease, studies]) => [disease,studies.length, ]) );setStudyCounts(diseaseStudyCounts); // Send data to AllStudiesPage } }, [allStudies, setStudyCounts]);const addToPool = (study, nodeId) => {const studyWithNode = { ...study, activeNodeId: nodeId };setStudyPool((prevPool) => {if (!prevPool.some((s) => s.id === study.id && s.activeNodeId === nodeId) ) {toast({title: "Study Added",description: "The study has been added to your pool",status: "success",duration: 3000,isClosable: true, });return [...prevPool, studyWithNode]; }toast({title: "Study Already in Pool",description: "This study is already in your pool",status: "warning",duration: 3000,isClosable: true, });return prevPool; }); };const removeFromPool = (studyToRemove) => {setStudyPool((prevPool) =>prevPool.filter( (study) =>!(study.id === studyToRemove.id &&study.activeNodeId === studyToRemove.activeNodeId ) ) ); };const handleProceed = () => {navigate("/multistudy/create-metastudy", { state: { studyPool } }); };if (loading) return <Loader />;if (error) return <Error errorMessage={error} />;return (<Box maxW="100%" px={4} pb={16}><HStack spacing={4} justify="center" py={4}><ButtoncolorScheme={isPublicView ? "gray" : "blue"}onClick={() => setIsPublicView(false)}>{/* My Library */} Processed Studies</Button><ButtoncolorScheme={isPublicView ? "blue" : "gray"}onClick={() => setIsPublicView(true)}position="relative">{/* Ready to Process */} Explore New Studies{showProgress && (<Boxposition="absolute"bottom="-30px"left="0"right="0"p={1}bg="white"borderRadius="md"boxShadow="md"width="full"><Progressvalue={fetchProgress.percentage}size="sm"colorScheme="green"hasStripeisAnimatedborderRadius="sm"mb={1}/><TextfontSize="xs"color="gray.700"textAlign="center"fontWeight="medium">{fetchProgress.current}/{fetchProgress.total}</Text></Box> )}</Button></HStack>{loading ? (<Loader /> // ✅ Show loader while fetching data ) : (<VStack spacing={3} align="stretch" width="full">{/* Always fetch both data sets, but toggle their visibility */}<Box display={isPublicView ? "block" : "none"} width="full"><PublicStudiesselectedDisease={diseaseParams}diseaseList={diseaseList}setStudyCountsPublic={setPublicStudyCounts}onOrganismsExtracted={onOrganismsExtracted}onSourcesExtracted={onSourcesExtracted}onStudyTypesExtracted={onStudyTypesExtracted}onTissuesExtracted={onTissuesExtracted}setPublicTissueCounts={setPublicTissueCounts}setPublicOrganismCounts={setPublicOrganismCounts}setPublicSourceCounts={setPublicSourceCounts}setPublicStudyTypeCounts={setPublicStudyTypeCounts}setFetchProgress={setFetchProgress}/></Box><Box display={!isPublicView ? "block" : "none"} width="full"><Box mb={4} bg="white" width="full"><Heading size="lg" mb={6}> Explore Studies</Heading><StudyPoolstudies={studyPool}onProceed={handleProceed}removeFromPool={removeFromPool}/></Box><Box mt="-2" mb="6"><SummaryWidgetProcessed studies={filteredStudies} /></Box>{filteredStudies.length > 0 ? (<StudyCardsContainerstudies={filteredStudies}addToPool={addToPool}studyPool={studyPool}/> ) : (<Box textAlign="center" py={10}><Heading size="md"> No Processed study for selected disease.</Heading></Box> )}</Box></VStack> )}</Box> );};function StudyCardsContainer({ studies, addToPool, studyPool }) {return (<GridtemplateColumns="repeat(auto-fill, minmax(300px, 1fr))"gap={8}width="full">{studies.map((study) => {const isInPool = studyPool.some((s) => s.id === study.id);return (<StudyCardkey={study.id}study={study}addToPool={addToPool}isInPool={isInPool}/> ); })}</Grid> );}export default AllStudiesMain;Public studies.jsximport { Box,Heading,Grid,Flex,Input,InputGroup,InputLeftElement,Spinner,Center,Button,useToast,} from "@chakra-ui/react";import { useState, useEffect, useMemo, useRef } from "react";import { SearchIcon } from "@chakra-ui/icons";import axios from "axios";import PublicStudyCard from "./PublicStudyCard";import ExportButton from "./ExportButton";import SummaryWidget from "./SummaryWidget";import { useQuery, useQueryClient } from "@tanstack/react-query";const PublicStudies = ({selectedDisease,onTissuesExtracted,diseaseList,onOrganismsExtracted,onSourcesExtracted,onStudyTypesExtracted,setStudyCountsPublic,setPublicTissueCounts,setPublicOrganismCounts,setPublicSourceCounts,setPublicStudyTypeCounts,setFetchProgress,}) => {const [publicStudies, setPublicStudies] = useState([]);const [searchQuery, setSearchQuery] = useState("");const [loading, setLoading] = useState(true);const [error, setError] = useState(null);const firstLoad = useRef(true);const [currentPage, setCurrentPage] = useState(1);const studiesPerPage = 20;const toast = useToast();const toastShownRef = useRef(false); // Track if toast has been shownconst [fetchedStudies, setFetchedStudies] = useState([]);const [filteredStudies, setFilteredStudies] = useState([]);const queryClient = useQueryClient();const saveInitialDiseaseParams = (params) => {try {sessionStorage.setItem("initialDiseaseParams", JSON.stringify(params)); } catch (error) {console.error("Error saving to sessionStorage:", error); } };const getInitialDiseaseParams = () => {try {const storedParams = sessionStorage.getItem("initialDiseaseParams");return storedParams ? JSON.parse(storedParams) : []; } catch (error) {console.error("Error reading from sessionStorage:", error);return []; } };// ✅ Extract URL parametersconst urlParams = useMemo(() => {const url = new URL(window.location.href);const params = {};for (const [key, value] of url.searchParams.entries()) {if (!params[key]) params[key] = [];params[key].push(value); }return params; }, [window.location.search]);const diseaseParams = useMemo(() => {const storedParams = getInitialDiseaseParams();let updatedParams = [...new Set([...storedParams, ...(urlParams.disease || [])]), ];if (updatedParams.length > 0) {saveInitialDiseaseParams(updatedParams); }return updatedParams; }, [urlParams.disease]); // Only depend on disease parameter changesconst dataFetchedRef = useRef(false);// Process partial data - O(s) where s is total studiesfunction processPartialData(data, diseaseList) {let combinedStudies = [];diseaseList.forEach((disease) => {if (Array.isArray(data[disease])) {const studiesWithDisease = data[disease].map((study) => ({...study,disease, }));combinedStudies = [...combinedStudies, ...studiesWithDisease]; } else {console.warn(`No valid study data found for disease: ${disease}`); } });return combinedStudies; }// Prepare full data request - O(s) where s is total studiesfunction prepareFullDataRequest(data, diseaseList) {const diseaseGseMapping = {};diseaseList.forEach((disease) => {if (Array.isArray(data[disease])) {const gseIds = data[disease].map((study) => study.accession_id);if (gseIds.length > 0) {diseaseGseMapping[disease] = gseIds; } } });return diseaseGseMapping; }// Enhanced version with improved time complexity - O(c+f) instead of O(c×f)function enhanceStudiesWithFullData(partialStudies, fullData) {// Create an index map for O(1) lookups - O(f) where f is total full studiesconst studyIndices = new Map();Object.entries(fullData).forEach(([disease, studies]) => {if (!Array.isArray(studies)) return;studies.forEach((study) => {if (study && study.accession_id) {// Create compound key: disease + accession_id for faster lookupsconst key = `${disease}:${study.accession_id}`;studyIndices.set(key, study); } }); });// Now use the indices for O(1) lookups - O(c) where c is number of partial studiesreturn partialStudies.map((partialStudy) => {const disease = partialStudy.disease;const key = `${disease}:${partialStudy.accession_id}`;const fullStudy = studyIndices.get(key);if (!fullStudy) return partialStudy;return {geo_accession: fullStudy.accession_id,title: Array.isArray(fullStudy.title)? fullStudy.title[0]: fullStudy.title,design: Array.isArray(fullStudy.design)? fullStudy.design[0]: fullStudy.design,platform: fullStudy.platform_names? fullStudy.platform_names[0]: Object.values(fullStudy.platform || {})[0] || "",publication: fullStudy.pub_med_URLs?.length? fullStudy.pub_med_URLs[0]: "",pubmed_id: fullStudy.pub_med_IDs,disease,description: Array.isArray(fullStudy.description) ? fullStudy.description[0] : fullStudy.description,samples: fullStudy.samples || [],organisms: fullStudy.organisms || [],source: partialStudy.source,table: (fullStudy.samples || []).map((sample) => ({sample_id: sample.sample_id,tissue_type: sample.tissue_type,characteristics: sample.characteristics, })),sample_count: (fullStudy.samples || []).length,assay_type: partialStudy.assay_type, }; }); }// Process all counts in a single pass - O(s) where s is total studiesconst processedCounts = useMemo(() => {if (publicStudies.length === 0) return null;const tissueCounts = {};const organismCounts = {};const sourceCounts = {};const studyTypeCounts = {};const studyCountsByDisease = {};const tissueTypes = new Set();const organisms = new Set();const sources = new Set();const studyTypes = new Set();publicStudies.forEach((study) => {// Disease countsif (study.disease) {studyCountsByDisease[study.disease] = (studyCountsByDisease[study.disease] || 0) + 1; }// Tissue types processingconst uniqueTissues = new Set();if (Array.isArray(study.table)) {study.table.forEach((entry) => {if (entry.tissue_type) {uniqueTissues.add(entry.tissue_type);tissueTypes.add(entry.tissue_type); } }); }if (Array.isArray(study.samples)) {study.samples.forEach((sample) => {if (sample.tissue_type) {uniqueTissues.add(sample.tissue_type);tissueTypes.add(sample.tissue_type); } }); }uniqueTissues.forEach((tissue) => {tissueCounts[tissue] = (tissueCounts[tissue] || 0) + 1; });// Organisms processingif (study.organisms) {const items = Array.isArray(study.organisms)? study.organisms: [study.organisms];const uniqueOrganisms = new Set(items);uniqueOrganisms.forEach((org) => {organisms.add(org);organismCounts[org] = (organismCounts[org] || 0) + 1; }); }// Source processingif (study.source) {sources.add(study.source);sourceCounts[study.source] = (sourceCounts[study.source] || 0) + 1; }// Study type processingif (study.assay_type) {studyTypes.add(study.assay_type);studyTypeCounts[study.assay_type] = (studyTypeCounts[study.assay_type] || 0) + 1; } });return {tissueCounts,organismCounts,sourceCounts,studyTypeCounts,studyCountsByDisease,tissueTypes: [...tissueTypes],organisms: [...organisms],sources: [...sources],studyTypes: [...studyTypes], }; }, [publicStudies]);// Effect to update parent state with processed countsuseEffect(() => {if (processedCounts) {// Update all the passed setterssetPublicTissueCounts(processedCounts.tissueCounts);setPublicOrganismCounts(processedCounts.organismCounts);setPublicSourceCounts(processedCounts.sourceCounts);setPublicStudyTypeCounts(processedCounts.studyTypeCounts);// Conditional callback updatesif (typeof setStudyCountsPublic === "function") {setStudyCountsPublic(processedCounts.studyCountsByDisease); }// Extraction callbacksif (typeof onTissuesExtracted === "function") {onTissuesExtracted(processedCounts.tissueTypes); }if (typeof onOrganismsExtracted === "function") {onOrganismsExtracted(processedCounts.organisms); }if (typeof onSourcesExtracted === "function") {onSourcesExtracted(processedCounts.sources); }if (typeof onStudyTypesExtracted === "function") {onStudyTypesExtracted(processedCounts.studyTypes); } } }, [processedCounts]);const createPersistentCacheKey = () => {const STORAGE_KEY = "persistentDiseaseCache";return {generateKey: (currentDiseases) => {// Retrieve previously stored diseasesconst storedDiseases = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "[]" );// Combine current and stored diseases, preserving original caseconst combinedDiseases = [...new Set([...storedDiseases, ...currentDiseases]), ].sort();// Store the updated disease listsessionStorage.setItem(STORAGE_KEY, JSON.stringify(combinedDiseases));// Create cache key with combined diseasesreturn ["publicStudies", JSON.stringify(combinedDiseases)]; },// Clear stored diseases if neededclear: () => {sessionStorage.removeItem(STORAGE_KEY); }, }; };// Use in your componentconst persistentCacheKeyManager = createPersistentCacheKey();const cacheKey = persistentCacheKeyManager.generateKey(diseaseList);const updateCacheWithNewDiseases = (newData, diseaseList) => {const sortedDiseases = JSON.stringify([...new Set(diseaseList)].sort());queryClient.setQueryData(["publicStudies", sortedDiseases], (oldData) => {if (!oldData) return newData;// Ensure comprehensive merging of studiesconst mergedStudies = [...oldData.filter( (oldStudy) => !newData.some((newStudy) => newStudy.id === oldStudy.id) ),...newData, ];return mergedStudies; }); };const {data: queryData,isLoading: queryLoading,error: queryError, } = useQuery({queryKey: cacheKey,queryFn: async () => {try {if (diseaseList.length === 0) {return null; }const storedDiseases = getInitialDiseaseParams();const urlDiseases = urlParams.disease || [];const allKnownDiseases = new Set([...storedDiseases, ...diseaseList]);const newDiseases = urlDiseases.filter((d) => !allKnownDiseases.has(d));const diseasesToFetch = [...new Set([...allKnownDiseases, ...newDiseases]), ];setFetchProgress({total: diseasesToFetch.length,current: 0,percentage: 0, });const filters = new URLSearchParams();diseasesToFetch.forEach((disease) =>filters.append("diseases", disease) );const queryString = filters.toString();const apiUrl = `/api/public-studies/partial-data${queryString ? `?${queryString}` : ""}`;const { data } = await axios.get(apiUrl, {headers: { accept: "application/json" }, });console.log(data)const combinedStudies = processPartialData(data, diseasesToFetch);const diseaseGseMapping = prepareFullDataRequest(data, diseasesToFetch);let finalStudies = combinedStudies;if (Object.keys(diseaseGseMapping).length > 0) {finalStudies = await fetchFullDataSequentially(combinedStudies,diseaseGseMapping,diseasesToFetch ); }updateCacheWithNewDiseases(finalStudies, diseasesToFetch);return finalStudies; } catch (error) {console.error("⌠Error in Query Function:", error);throw error; // Ensure React Query recognizes the error } },staleTime: 30 * 60 * 1000, // 30 minutescacheTime: 30 * 60 * 1000, // 30 minutesrefetchOnWindowFocus: false,enabled: diseaseList.length > 0, });// Async function to fetch full data sequentially (extracted from original code)const fetchFullDataSequentially = async (combinedStudies,diseaseGseMapping,diseasesToFetch ) => {let enhancedStudies = [...combinedStudies];const diseaseEntries = Object.entries(diseaseGseMapping);setFetchProgress({total: diseaseEntries.length,current: 0,percentage: 0, }); // **Start full data progress**for (const [index, [disease, gseIds]] of diseaseEntries.entries()) {try {const fullDataPayload = [{ disease, accession_ids: gseIds }];console.log(fullDataPayload)const fullDataResponse = await axios.post("/api/public-studies/full-data",fullDataPayload, {headers: {accept: "application/json","Content-Type": "application/json", }, } );// Enhance studies with fetched full dataenhancedStudies = enhanceStudiesWithFullData(enhancedStudies,fullDataResponse.data );// **Update state incrementally**setPublicStudies([...enhancedStudies]);setFetchedStudies([...enhancedStudies]);const progressPercentage = Math.round( ((index + 1) / diseaseEntries.length) * 100 );setFetchProgress({total: diseaseEntries.length,current: index + 1,percentage: progressPercentage, }); } catch (fullDataError) {console.error(`Error fetching full data for ${disease}:`,fullDataError );toast({title: `Error loading full study data for ${disease}`,description: "There was an issue fetching full study details.",status: "error",duration: 5000,isClosable: true, }); } }return enhancedStudies; };// Effect to handle query resultsuseEffect(() => {if (queryData) {// Set studiessetPublicStudies(queryData);setFetchedStudies(queryData);// Process counts// processAllCounts(queryData);// Save initial disease paramssaveInitialDiseaseParams(diseaseParams);// Toast for successful loadtoast({title: "Studies loaded successfully!",description: "Public studies have been updated.",status: "success",duration: 3000,isClosable: true, });// Set loading statesetLoading(false); } }, [queryData]);// Error handling effectuseEffect(() => {if (queryError) {console.error("Error fetching studies:", queryError);setError("Failed to fetch public studies");toast({title: "Error fetching studies",description: "Could not load public studies. Please try again later.",status: "error",duration: 5000,isClosable: true, });setLoading(false); } }, [queryError]);// Apply filtersuseEffect(() => {// Apply filters whenever fetchedStudies, urlParams, or searchQuery changesif (!fetchedStudies.length) {setFilteredStudies([]);return; }let filtered = [...fetchedStudies];// Disease filterif (urlParams.disease && urlParams.disease.length > 0) {filtered = filtered.filter( (study) =>study.disease &&urlParams.disease.some((disease) => study.disease === disease) ); }// Tissue filterif (urlParams.tissue && urlParams.tissue.length > 0) {filtered = filtered.filter((study) =>study.table?.some((entry) =>urlParams.tissue.some((tissue) => entry.tissue_type?.includes(tissue)) ) ); }// Source filterif (urlParams.source && urlParams.source.length > 0) {filtered = filtered.filter( (study) =>study.source &&urlParams.source.some((source) => study.source === source) ); }// Organism filterif (urlParams.organism && urlParams.organism.length > 0) {filtered = filtered.filter( (study) =>Array.isArray(study.organisms) &&urlParams.organism.some((organism) =>study.organisms.includes(organism) ) ); }// Study Type filterif (urlParams.assay_type && urlParams.assay_type.length > 0) {filtered = filtered.filter( (study) =>study.assay_type &&urlParams.assay_type.some((type) => study.assay_type === type) ); }// Search Query filterif (searchQuery) {filtered = filtered.filter( (study) =>study.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||study.geo_accession?.toLowerCase().includes(searchQuery.toLowerCase()) ); }setFilteredStudies(filtered); }, [fetchedStudies, urlParams, searchQuery]);// // Loading state// if (loading) {// return (// <Box width="full" height="400px">// <Center height="100%">// <Spinner size="xl" color="blue.500" thickness="4px" />// </Center>// </Box>// );// }// // Error state// if (error) {// return (// <Box p={6} textAlign="center" color="red.500">// {error}// </Box>// );// }// Empty disease selection stateif (diseaseParams.length === 0 && (!selectedDisease || selectedDisease === "") ) {return (<Box p={6} textAlign="center"> Fetching public studies for the selected diseases</Box> ); }// Empty search results stateif (publicStudies.length === 0) {return (<Box p={6} textAlign="center"> Fetching public studies for the selected diseases</Box> ); }// Calculate paginationconst totalPages = Math.ceil(filteredStudies.length / studiesPerPage);const startIndex = (currentPage - 1) * studiesPerPage;const paginatedStudies = filteredStudies.slice(startIndex,startIndex + studiesPerPage );// Main content renderreturn (<Box width="full"><Flex justify="space-between" align="center" mb={4}><Heading size="lg">Explore Studies</Heading><ExportButtonpublicStudies={filteredStudies}fileName={"PublicStudies"}/></Flex><InputGroup width="40%" mb={6}><InputLeftElement pointerEvents="none"><SearchIcon color="gray.400" /></InputLeftElement><Inputplaceholder="Search within results..."value={searchQuery}onChange={(e) => setSearchQuery(e.target.value)}/></InputGroup><SummaryWidget studies={filteredStudies} disease={diseaseList} /><GridtemplateColumns="repeat(auto-fill, minmax(100%, 1fr))"gap={6}width="full"mt="4">{paginatedStudies.length > 0 ? (paginatedStudies.map((study) => (<PublicStudyCard key={study.accession_id} study={study} /> )) ) : (<Box textAlign="center">No matching studies found.</Box> )}</Grid>{/* Pagination Controls */}<Flex justify="center" mt={6}><ButtonisDisabled={currentPage === 1}onClick={() => setCurrentPage(currentPage - 1)}mr={2}> Previous</Button><Box mx={4} fontWeight="bold"> Page {currentPage} of {totalPages}</Box><ButtonisDisabled={currentPage === totalPages}onClick={() => setCurrentPage(currentPage + 1)}> Next</Button></Flex></Box> );};export default PublicStudies;eg function response from llm get_studies_list_by_disease toolcontent:parts:0:functionResponse:id: "adk-d1c570bc-baef-4105-ac89-ca0be9bb326d"name: "get_studies_list_by_disease"response:result:content:0:type: "text"text: "{'processed_studies': [{'id': 'aa244641-2579-4440-9019-92db5e5c8374', 'organisms': ['Homo sapiens'], 'diseases': ['Kawasaki disease'], 'title': 'Single-cell sequencing of peripheral blood mononuclear cells in acute Kawasaki disease', 'publish_date': '2025-02-03', 'tissues': ['PBMC'], 'cell_count': 106453, 'sample_count': 15, 'source': 'NCBI', 'human_readable_study_id': 'KD-GSE168732', 'assay_type': 'scRNA'}], 'public_studies': {'Kawasaki disease': [{'accession_id': 'GSE284775', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE253945', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289270', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289269', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289268', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE266059', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE255555', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE184661', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE254657', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE242752', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE183390', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE248021', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE246716', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE236833', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE235994', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE223841', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE172526', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE172514', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE171903', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE171901', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE203542', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE200743', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE181342', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE165519', 'organisms': ['Macaca mulatta'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE210094', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE178491', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE165693', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE184505', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE178765', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE183716', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE152450', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE149851', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE135087', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE146292', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE161172', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE150549', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE141072', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE142691', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE133159', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE138364', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE131996', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE120012', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE108884', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE116633', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE115950', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106882', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106636', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106489', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE79435', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE93670', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE64486', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE67437', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}]}}"structuredContent:result: "{'processed_studies': [{'id': 'aa244641-2579-4440-9019-92db5e5c8374', 'organisms': ['Homo sapiens'], 'diseases': ['Kawasaki disease'], 'title': 'Single-cell sequencing of peripheral blood mononuclear cells in acute Kawasaki disease', 'publish_date': '2025-02-03', 'tissues': ['PBMC'], 'cell_count': 106453, 'sample_count': 15, 'source': 'NCBI', 'human_readable_study_id': 'KD-GSE168732', 'assay_type': 'scRNA'}], 'public_studies': {'Kawasaki disease': [{'accession_id': 'GSE284775', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE253945', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289270', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289269', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE289268', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE266059', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE255555', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE184661', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE254657', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE242752', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE183390', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE248021', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE246716', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE236833', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE235994', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE223841', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE172526', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE172514', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE171903', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE171901', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE203542', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE200743', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE181342', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE165519', 'organisms': ['Macaca mulatta'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE210094', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE178491', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE165693', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE184505', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE178765', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE183716', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE152450', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE149851', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE135087', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE146292', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE161172', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE150549', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE141072', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE142691', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE133159', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE138364', 'organisms': ['Homo sapiens'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE131996', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE120012', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE108884', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE116633', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE115950', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106882', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106636', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE106489', 'organisms': ['Mus musculus'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE79435', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE93670', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}, {'accession_id': 'GSE64486', 'organisms': ['Homo sapiens'], 'assay_type': 'scRNA', 'source': 'NCBI'}, {'accession_id': 'GSE67437', 'organisms': ['Mus musculus'], 'assay_type': 'bulkRNA', 'source': 'NCBI'}]}}"isError: falserole: "user"invocationId: "e-b818ca42-81b9-4927-ba8c-dc6509007967"author: "distill_agent"search_studies tool resultcontent:parts:0:functionResponse:id: "adk-791795f2-4f87-467d-8d98-87b608178122"name: "search_studies"response:result:content:0:type: "text"text: "Id(uuid),title,description "isError: truechange my home page accordingly
You can send messages while the preview loads