Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.
24 changes: 13 additions & 11 deletions src/@types/parseable/api/about.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
export type AboutData ={
commit : string;
deploymentId : string;
latestVersion : string;
license : string;
mode : string;
staging : string;
store : string;
updateAvailable : boolean;
version : string;
}
export type AboutData = {
commit: string;
deploymentId: string;
latestVersion: string;
license: string;
mode: string;
staging: string;
store: string;
updateAvailable: boolean;
version: string;
llmActive: boolean;
llmProvider: string;
};
1 change: 1 addition & 0 deletions src/api/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export const USER_PASSWORD_URL = (username: string) => `${USER_URL(username)}/ge

// LLM queries
export const LLM_QUERY_URL = `${API_V1}/llm`;
export const IS_LLM_ACTIVE_URL = `${LLM_QUERY_URL}/isactive`;
141 changes: 72 additions & 69 deletions src/components/Navbar/infoModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Button, Modal, Text, Tooltip, px } from '@mantine/core';
import { FC, useEffect } from 'react';
import { FC, useEffect, useMemo } from 'react';
import { useInfoModalStyles } from './styles';
import { useGetAbout } from '@/hooks/useGetAbout';
import { IconAlertCircle, IconBook2, IconBrandGithub, IconBrandSlack, IconBusinessplan } from '@tabler/icons-react';
Expand Down Expand Up @@ -69,6 +69,14 @@ const InfoModal: FC<InfoModalProps> = (props) => {
};
}, []);

const llmStatus = useMemo(() => {
let status = 'LLM API Key not set';
if (data?.llmActive) {
status = `${data.llmProvider} configured`;
}
return status;
}, [data?.llmActive]);

const { classes } = useInfoModalStyles();
const {
container,
Expand All @@ -80,96 +88,91 @@ const InfoModal: FC<InfoModalProps> = (props) => {
aboutTextKey,
aboutTextValue,
aboutTextInnerBox,
actionBtnRed
actionBtnRed,
} = classes;

return (
<Modal
opened={opened}
onClose={close}
withinPortal
withCloseButton={false}
size="xl"
centered>
<Modal opened={opened} onClose={close} withinPortal withCloseButton={false} size="xl" centered>
<Box className={container}>

<Text className={aboutTitle}>About Parseable</Text>
<Text className={aboutDescription} id="info-modal-description">Important info about your Parseable deployment</Text>
{error ? (
<Text className={aboutDescription}>Error...</Text>
) : loading ? (
<Text className={aboutDescription}>Loading...</Text>
) : data ? (
<>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> License: </Text>
<Text className={aboutTextValue}> {data.license} </Text>
<Button
<Text className={aboutTitle}>About Parseable</Text>
<Text className={aboutDescription} id="info-modal-description">
Important info about your Parseable deployment
</Text>
{error ? (
<Text className={aboutDescription}>Error...</Text>
) : loading ? (
<Text className={aboutDescription}>Loading...</Text>
) : data ? (
<>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> License: </Text>
<Text className={aboutTextValue}> {data.license} </Text>
<Button
variant="outline"
component={'a'}
href="mailto:[email protected]?subject=Production%20Support%20Query"
target="_blank"
className={actionBtn}
>
className={actionBtn}>
Upgrade to production support
</Button>
</Box>
</Box>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Commit: </Text>
<Text className={aboutTextValue}> {data.commit} </Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Version: </Text>
<Text className={aboutTextValue}> {data.version} </Text>
{data.updateAvailable ? (
<Button
</Box>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Commit: </Text>
<Text className={aboutTextValue}> {data.commit} </Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Version: </Text>
<Text className={aboutTextValue}> {data.version} </Text>
{data.updateAvailable ? (
<Button
variant="outline"
component={'a'}
href="https://github.com/parseablehq/parseable/releases/latest"
target="_blank"
className={actionBtnRed}
leftIcon={<IconAlertCircle size={px('1.2rem')} stroke={1.5} />}
>
leftIcon={<IconAlertCircle size={px('1.2rem')} stroke={1.5} />}>
Upgrade to latest version {data.latestVersion}
</Button> ): null}
</Box>

</Button>
) : null}
</Box>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Deployment Id: </Text>
<Text className={aboutTextValue}> {data.deploymentId} </Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Mode</Text>
<Text className={aboutTextValue}>{data.mode}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Staging</Text>
<Text className={aboutTextValue}>{data.staging}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Store</Text>
<Text className={aboutTextValue}>{data.store}</Text>
</Box>
</Box>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Deployment Id: </Text>
<Text className={aboutTextValue}> {data.deploymentId} </Text>
</Box>
</>
) : null}

<Text className={aboutTitle}>Need help?</Text>
<Text className={aboutDescription}>Ensure uninterrupted deployment</Text>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Mode</Text>
<Text className={aboutTextValue}>{data.mode}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Staging</Text>
<Text className={aboutTextValue}>{data.staging}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Store</Text>
<Text className={aboutTextValue}>{data.store}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>LLM Status</Text>
<Text className={aboutTextValue}>{llmStatus}</Text>
</Box>
</Box>
</>
) : null}

<Box mt={15} className={helpIconContainer}>
{helpResources.map((data) => (
<HelpCard key={data.title} data={data} />
))}
</Box>
<Text className={aboutTitle}>Need help?</Text>
<Text className={aboutDescription}>Ensure uninterrupted deployment</Text>

<Box mt={15} className={helpIconContainer}>
{helpResources.map((data) => (
<HelpCard key={data.title} data={data} />
))}
</Box>

</Box>
</Modal>
);
};
Expand Down
52 changes: 34 additions & 18 deletions src/pages/Query/QueryCodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useEffect } from 'react';
import React, { FC, useCallback, useEffect, useMemo } from 'react';
import Editor from '@monaco-editor/react';
import { useQueryPageContext } from './Context';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
Expand All @@ -13,6 +13,7 @@ import dayjs from 'dayjs';
import { notify } from '@/utils/notification';
import { Axios } from '@/api/axios';
import { LLM_QUERY_URL } from '@/api/constants';
import { useGetAbout } from '@/hooks/useGetAbout';

const QueryCodeEditor: FC = () => {
const {
Expand All @@ -30,13 +31,20 @@ const QueryCodeEditor: FC = () => {
const [currentStreamName, setCurrentStreamName] = useMountedState<string>(subLogQuery.get().streamName);
const [query, setQuery] = useMountedState<string>('');
const [aiQuery, setAiQuery] = useMountedState('Show all records');
const { data: aboutData, getAbout } = useGetAbout();
const isLlmActive = useMemo(() => aboutData?.llmActive, [aboutData?.llmActive]);

const handleAIGenerate = async () => {
const handleAIGenerate = useCallback(async () => {
if (!aiQuery?.length) {
notify({ message: 'Please enter a valid query' });
return;
}
notify({ message: 'AI based SQL being generated.', title: 'Getting suggestions', autoClose: 3000, color: 'blue' });
notify({
message: 'AI based SQL being generated.',
title: 'Getting suggestions',
autoClose: 3000,
color: 'blue',
});

const resp = await Axios().post(LLM_QUERY_URL, { prompt: aiQuery, stream: currentStreamName });
if (resp.status !== 200) {
Expand All @@ -51,7 +59,7 @@ const QueryCodeEditor: FC = () => {
const warningMsg =
'-- Parseable AI is experimental and may produce incorrect answers\n-- Always verify the generated SQL before executing\n\n';
setQuery(warningMsg + resp.data);
};
}, [aiQuery]);

const handleEditorChange = (code: any) => {
setQuery(code);
Expand Down Expand Up @@ -91,6 +99,7 @@ const QueryCodeEditor: FC = () => {
if (subLogQuery.get().streamName) {
setQuery(`SELECT * FROM ${subLogQuery.get().streamName} LIMIT 100 ; `);
}
getAbout();
}, []);

function handleEditorDidMount(editor: any, monaco: any) {
Expand Down Expand Up @@ -176,6 +185,11 @@ const QueryCodeEditor: FC = () => {
<Box className={container}>
<Text className={textContext}>Query</Text>
<Box style={{ height: '100%', width: '100%', textAlign: 'right' }}>
{!isLlmActive ? (
<a style={{ marginRight: '2rem' }} href="https://www.parseable.io/docs/api/llm-queries">
Enable SQL generation with OpenAI
</a>
) : null}
<Tooltip
label={`View Schema for ${subLogQuery.get().streamName}`}
sx={{ color: 'white', backgroundColor: 'black' }}
Expand Down Expand Up @@ -206,20 +220,22 @@ const QueryCodeEditor: FC = () => {
</Box>
</Box>
<Box sx={{ marginTop: '5px', height: 'calc(100% - 60px)' }}>
<Box className="flex" style={{ display: 'flex', margin: '15px', flexWrap: 'wrap' }}>
<Input
type="text"
name="ai_query"
id="ai_query"
style={{ minWidth: '85%', margin: '2px 20px 10px 0' }}
value={aiQuery}
onChange={(e) => setAiQuery(e.target.value)}
placeholder="Ask Parseable AI"
/>
<Button variant="gradient" onClick={handleAIGenerate}>
Generate SQL
</Button>
</Box>
{isLlmActive ? (
<Box className="flex" style={{ display: 'flex', margin: '15px', flexWrap: 'wrap' }}>
<Input
type="text"
name="ai_query"
id="ai_query"
style={{ minWidth: '85%', margin: '2px 20px 10px 0' }}
value={aiQuery}
onChange={(e) => setAiQuery(e.target.value)}
placeholder="Ask Parseable AI"
/>
<Button variant="gradient" onClick={handleAIGenerate}>
Generate SQL
</Button>
</Box>
) : null}
<Editor
height={'100%'}
defaultLanguage="sql"
Expand Down