From 8e06c6ff792257b460da00548af5a479a2ff3f81 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Fri, 19 Jul 2024 13:53:22 +0530 Subject: [PATCH 01/52] data analysis page --- src/assets/icons/content_copy.svg | 3 + src/assets/icons/dalgoIcon.svg | 5 + src/assets/icons/folder.svg | 3 + src/assets/icons/info.svg | 8 + src/assets/icons/thumb_up (1).svg | 4 + src/assets/icons/thumb_up.svg | 4 + src/config/menu.tsx | 9 + src/pages/analysis/data-analysis.tsx | 346 +++++++++++++++++++++++++++ 8 files changed, 382 insertions(+) create mode 100644 src/assets/icons/content_copy.svg create mode 100644 src/assets/icons/dalgoIcon.svg create mode 100644 src/assets/icons/folder.svg create mode 100644 src/assets/icons/info.svg create mode 100644 src/assets/icons/thumb_up (1).svg create mode 100644 src/assets/icons/thumb_up.svg create mode 100644 src/pages/analysis/data-analysis.tsx diff --git a/src/assets/icons/content_copy.svg b/src/assets/icons/content_copy.svg new file mode 100644 index 00000000..3da4c47c --- /dev/null +++ b/src/assets/icons/content_copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/dalgoIcon.svg b/src/assets/icons/dalgoIcon.svg new file mode 100644 index 00000000..6343812a --- /dev/null +++ b/src/assets/icons/dalgoIcon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/folder.svg b/src/assets/icons/folder.svg new file mode 100644 index 00000000..7d45aa61 --- /dev/null +++ b/src/assets/icons/folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/info.svg b/src/assets/icons/info.svg new file mode 100644 index 00000000..ac035662 --- /dev/null +++ b/src/assets/icons/info.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/thumb_up (1).svg b/src/assets/icons/thumb_up (1).svg new file mode 100644 index 00000000..df8aebca --- /dev/null +++ b/src/assets/icons/thumb_up (1).svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/thumb_up.svg b/src/assets/icons/thumb_up.svg new file mode 100644 index 00000000..3a6775ca --- /dev/null +++ b/src/assets/icons/thumb_up.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/config/menu.tsx b/src/config/menu.tsx index c24106e7..d3f11484 100644 --- a/src/config/menu.tsx +++ b/src/config/menu.tsx @@ -45,6 +45,15 @@ export const sideMenu: MenuOption[] = [ className: 'usage_walkthrough', minimize: true, }, + { + index: 1.2, + title: 'Data Analysis', + path: '/analysis/data-analysis', + icon: (selected: boolean) => , + parent: 1, + className: 'data_analysis', + minimize: true, + }, { index: 2, title: 'Pipeline overview', diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx new file mode 100644 index 00000000..93a36b50 --- /dev/null +++ b/src/pages/analysis/data-analysis.tsx @@ -0,0 +1,346 @@ +import { Box, Button, TextField, Typography } from '@mui/material'; +import Image from 'next/image'; +import SavedIcon from '@/assets/icons/folder.svg'; +import InfoIcon from '@/assets/icons/info.svg'; +import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; +import CopyIcon from '@/assets/icons/content_copy.svg'; +import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; +import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; +export default function DataAnalysis() { + return ( + <> + + + + + + Parameters + logout icon + + + + logout icon + Saved Sessions + + + + + + + {/* second box */} + +
+
+ {/* Third box with sql editor */} + + + + SQL Filter* + + + {/* This contains the sql filter */} + + + + {/* foruth box with some buttons */} + + + + + Select a prompt* + + + (Choose any one from the given prompts) + + + + + + + + + + + + OR + + + + + +
+
+ + {/* ANALYSIS ONE */} + + {/* inside the bottom box we will keep everything */} + + + LLM Summary + info icon + + {/* THIS IS THE SUMMARY UI PORTION */} + + logout icon + + + logout icon + logout icon + logout icon + + + + + + + + +
+ + ); +} + +const customCss = { + display: 'flex', + boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', + backgroundColor: '#FFFFFF', + borderRadius: '12px', + padding: '2rem', + // borderColor: '#FFFFFF', +}; From 753c6f54998f7a9ba69595831a2cdcda085f73b9 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Fri, 19 Jul 2024 15:44:52 +0530 Subject: [PATCH 02/52] added functions in sql write --- src/components/DataAnalysis/LLMSummary.tsx | 125 ++++++++ src/components/DataAnalysis/SqlWrite.tsx | 266 ++++++++++++++++ src/pages/analysis/data-analysis.tsx | 338 +-------------------- 3 files changed, 399 insertions(+), 330 deletions(-) create mode 100644 src/components/DataAnalysis/LLMSummary.tsx create mode 100644 src/components/DataAnalysis/SqlWrite.tsx diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx new file mode 100644 index 00000000..ecaa54aa --- /dev/null +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -0,0 +1,125 @@ +import { Box, Button } from '@mui/material'; +import Image from 'next/image'; +import InfoIcon from '@/assets/icons/info.svg'; +import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; +import CopyIcon from '@/assets/icons/content_copy.svg'; +import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; +import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; + +export const LLMSummary = () => { + return ( + <> + + {/* inside the bottom box we will keep everything */} + + + LLM Summary + info icon + + {/* THIS IS THE SUMMARY UI PORTION */} + + logout icon + + + logout icon + logout icon + logout icon + + + + + + + + + + ); +}; + +const customCss = { + display: 'flex', + boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', + backgroundColor: '#FFFFFF', + borderRadius: '12px', + padding: '2rem', + // borderColor: '#FFFFFF', +}; diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx new file mode 100644 index 00000000..9532e943 --- /dev/null +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -0,0 +1,266 @@ +import { Box, Button, TextField, Typography } from '@mui/material'; +import Image from 'next/image'; +import SavedIcon from '@/assets/icons/folder.svg'; +import InfoIcon from '@/assets/icons/info.svg'; + +import { useState } from 'react'; + +export const SqlWrite = ()=>{ + const [customPromptToggle, setCustomPromptToggle] = useState(false); + const [customPrompt, setCustomPrompt] = useState(""); + const [sqlText, setSqlText] = useState(""); + return <> + + + + + + Parameters + logout icon + + + + logout icon + Saved Sessions + + + + + + + {/* second box */} + +
+
+ {/* Third box with sql editor */} + + + + SQL Filter* + + + {/* This contains the sql filter */} + {setSqlText(e.target.value)}} + /> + + + {/* foruth box with some buttons */} + + + + + Select a prompt* + + + (Choose any one from the given prompts) + + + + + + + + + + + + OR + + + {customPromptToggle ? ( + + + Custom Prompt + + + {setCustomPrompt(e.target.value)}} + /> + + ) : ( + + )} + + +
+
+ +} + +const customCss = { + display: 'flex', + boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', + backgroundColor: '#FFFFFF', + borderRadius: '12px', + padding: '2rem', + // borderColor: '#FFFFFF', + }; + \ No newline at end of file diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index 93a36b50..cba6fe78 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -1,11 +1,7 @@ -import { Box, Button, TextField, Typography } from '@mui/material'; -import Image from 'next/image'; -import SavedIcon from '@/assets/icons/folder.svg'; -import InfoIcon from '@/assets/icons/info.svg'; -import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; -import CopyIcon from '@/assets/icons/content_copy.svg'; -import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; -import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; +import { Box } from '@mui/material'; + +import { LLMSummary } from '@/components/DataAnalysis/LLMSummary'; +import { SqlWrite } from '@/components/DataAnalysis/SqlWrite'; export default function DataAnalysis() { return ( <> @@ -17,330 +13,12 @@ export default function DataAnalysis() { gap: '1rem', }} > - - - - - Parameters - logout icon - - - - logout icon - Saved Sessions - - - - - - - {/* second box */} - -
-
- {/* Third box with sql editor */} - - - - SQL Filter* - - - {/* This contains the sql filter */} - - - - {/* foruth box with some buttons */} - - - - - Select a prompt* - - - (Choose any one from the given prompts) - - - - - - - - - - - - OR - - - - - -
-
- - {/* ANALYSIS ONE */} - - {/* inside the bottom box we will keep everything */} - - - LLM Summary - info icon - - {/* THIS IS THE SUMMARY UI PORTION */} - - logout icon - - - logout icon - logout icon - logout icon - - - - - - - - + {/* Sql filter */} + + {/* LLM summary */} + ); } -const customCss = { - display: 'flex', - boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', - backgroundColor: '#FFFFFF', - borderRadius: '12px', - padding: '2rem', - // borderColor: '#FFFFFF', -}; From f3531b0e4fff5f35ca038b46ca02db145dc3f096 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Mon, 22 Jul 2024 13:49:29 +0530 Subject: [PATCH 03/52] worked on the table and the full screen loader --- src/assets/icons/arrow_back_ios.svg | 8 + src/assets/icons/close_small.svg | 8 + src/components/DataAnalysis/SavedSession.tsx | 321 ++++++++++++ src/components/DataAnalysis/SqlWrite.tsx | 489 ++++++++++-------- src/components/Dialog/DataDialog.tsx | 64 +++ .../UI/FullScreenLoader/FullScreenLoader.tsx | 29 ++ 6 files changed, 712 insertions(+), 207 deletions(-) create mode 100644 src/assets/icons/arrow_back_ios.svg create mode 100644 src/assets/icons/close_small.svg create mode 100644 src/components/DataAnalysis/SavedSession.tsx create mode 100644 src/components/Dialog/DataDialog.tsx create mode 100644 src/components/UI/FullScreenLoader/FullScreenLoader.tsx diff --git a/src/assets/icons/arrow_back_ios.svg b/src/assets/icons/arrow_back_ios.svg new file mode 100644 index 00000000..cf102427 --- /dev/null +++ b/src/assets/icons/arrow_back_ios.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/close_small.svg b/src/assets/icons/close_small.svg new file mode 100644 index 00000000..45e22332 --- /dev/null +++ b/src/assets/icons/close_small.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx new file mode 100644 index 00000000..ddd81d92 --- /dev/null +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -0,0 +1,321 @@ +import { + Box, + Dialog, + Table, + TableBody, + TableCell, + TableContainer, + Paper, + TableHead, + TableRow, + Typography, + Button, +} from '@mui/material'; + +import Image from 'next/image'; +import InfoIcon from '@/assets/icons/info.svg'; +import CloseIcon from "@/assets/icons/close_small.svg"; +import ArrowIcon from "@/assets/icons/arrow_back_ios.svg" + +const dataArray = [ + { + sno: 1, + createdOn: '2024-07-01', + updatedOn: '2024-07-02', + name: 'John Doe', + createdBy: 'admin@example.com', + }, + { + sno: 2, + createdOn: '2024-07-02', + updatedOn: '2024-07-03', + name: 'Jane Smith', + createdBy: 'admin@example.com', + }, + { + sno: 3, + createdOn: '2024-07-03', + updatedOn: '2024-07-04', + name: 'Alice Johnson', + createdBy: 'moderator@example.com', + }, + { + sno: 4, + createdOn: '2024-07-04', + updatedOn: '2024-07-05', + name: 'Bob Brown', + createdBy: 'admin@example.com', + }, + { + sno: 5, + createdOn: '2024-07-05', + updatedOn: '2024-07-06', + name: 'Charlie Davis', + createdBy: 'user@example.com', + }, + { + sno: 6, + createdOn: '2024-07-04', + updatedOn: '2024-07-05', + name: 'Bob Brown', + createdBy: 'admin@example.com', + }, + { + sno: 7, + createdOn: '2024-07-05', + updatedOn: '2024-07-06', + name: 'Charlie Davis', + createdBy: 'user@example.com', + }, + { + sno: 8, + createdOn: '2024-07-04', + updatedOn: '2024-07-05', + name: 'Bob Brown', + createdBy: 'admin@example.com', + }, + { + sno: 9, + createdOn: '2024-07-05', + updatedOn: '2024-07-06', + name: 'Charlie Davis', + createdBy: 'user@example.com', + }, + { + sno: 10, + createdOn: '2024-07-04', + updatedOn: '2024-07-05', + name: 'Bob Brown', + createdBy: 'admin@example.com', + }, + { + sno: 11, + createdOn: '2024-07-05', + updatedOn: '2024-07-06', + name: 'Charlie Davis', + createdBy: 'user@example.com', + }, +]; + +export const SavedSession = ({ open, onClose }:{open: boolean, onClose:any}) => { + return ( + <> + + {/* MAIN BOX */} + + + + Saved Sessions + info icon + + close icon + + + + + + + + + + Created On + + + Updated On + + + Name + + + Created By + + + + + {dataArray.map((row) => ( + + + {row.sno} + + + {row.createdOn} + + + {row.updatedOn} + + + {row.name} + + + {row.createdBy} + + + + ))} + +
+
+
+
+ + ); +}; diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 9532e943..9a7e68c2 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -2,265 +2,340 @@ import { Box, Button, TextField, Typography } from '@mui/material'; import Image from 'next/image'; import SavedIcon from '@/assets/icons/folder.svg'; import InfoIcon from '@/assets/icons/info.svg'; - +import CloseIcon from '@/assets/icons/close_small.svg'; import { useState } from 'react'; +import { SavedSession } from './SavedSession'; +import { FullPageLoader } from '../UI/FullScreenLoader/FullScreenLoader'; -export const SqlWrite = ()=>{ - const [customPromptToggle, setCustomPromptToggle] = useState(false); - const [customPrompt, setCustomPrompt] = useState(""); - const [sqlText, setSqlText] = useState(""); - return <> - - - +export const SqlWrite = () => { + const [customPromptToggle, setCustomPromptToggle] = useState(false); + const [customPrompt, setCustomPrompt] = useState(''); + const [defaultPrompt, setDefaultPrompt] = useState(''); + const [sqlText, setSqlText] = useState(''); + const [loading, setLoading] = useState(false); + const [openSavedSessionDialog, setOpenSavedSessionDialog] = useState(false); + const handleCloseSavedSession = () => { + setOpenSavedSessionDialog(false); + }; + const handlePromptSelection = (promptText: string) => { + if (customPromptToggle) { + setCustomPrompt(''); + setCustomPromptToggle(false); + } + setDefaultPrompt(promptText); + }; + const handleSubmit = () => { + if ((sqlText && customPrompt) || (sqlText && defaultPrompt)) { + //api call + setLoading(true); + setTimeout(() => { + setLoading(false); + }, 2000); + } + }; + return ( + <> + + + + + Parameters + logout icon + - { + setOpenSavedSessionDialog(true); }} > - Parameters logout icon + Saved Sessions + + + + + + {/* second box */} + +
+
+ {/* Third box with sql editor */} + + + + SQL Filter* + + + {/* This contains the sql filter */} + { + setSqlText(e.target.value); + }} + /> + + + {/* foruth box with some buttons */} + + - - logout icon - Saved Sessions - - - - + Select a prompt* + + + (Choose any one from the given prompts) + - {/* second box */} - -
-
- {/* Third box with sql editor */} - - - SQL Filter* - - - {/* This contains the sql filter */} - {setSqlText(e.target.value)}} - /> - - - {/* foruth box with some buttons */} - { + handlePromptSelection('Brightspots'); + }} + > + + Brightspots + + + + + + + + OR + + + {customPromptToggle ? ( + - - Select a prompt* - - Custom Prompt + { + setCustomPromptToggle(false); + setCustomPrompt(''); }} - > - (Choose any one from the given prompts) - + alt="close icon" + /> + { + setCustomPrompt(e.target.value); + }} + /> - - { + if (defaultPrompt) { + setDefaultPrompt(''); + } + setCustomPromptToggle(true); }} > - - - - - - - OR - - - {customPromptToggle ? ( - - - Custom Prompt - - - {setCustomPrompt(e.target.value)}} - /> - - ) : ( - - )} - - + + Add a custom prompt + + )}
+
+
+ + + {loading&& } -} + ); +}; const customCss = { - display: 'flex', - boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', - backgroundColor: '#FFFFFF', - borderRadius: '12px', - padding: '2rem', - // borderColor: '#FFFFFF', - }; - \ No newline at end of file + display: 'flex', + boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', + backgroundColor: '#FFFFFF', + borderRadius: '12px', + padding: '2rem', + // borderColor: '#FFFFFF', +}; diff --git a/src/components/Dialog/DataDialog.tsx b/src/components/Dialog/DataDialog.tsx new file mode 100644 index 00000000..7f435434 --- /dev/null +++ b/src/components/Dialog/DataDialog.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Dialog, DialogTitle } from '@mui/material'; +// import { makeStyles } from '@material-ui/core/styles'; +// import Button from '@material-ui/core/Button'; +// import Avatar from '@material-ui/core/Avatar'; +// import List from '@material-ui/core/List'; +// import ListItem from '@material-ui/core/ListItem'; +// import ListItemAvatar from '@material-ui/core/ListItemAvatar'; +// import ListItemText from '@material-ui/core/ListItemText'; +// import DialogTitle from '@material-ui/core/DialogTitle'; +// import Dialog from '@material-ui/core/Dialog'; +// import PersonIcon from '@material-ui/icons/Person'; +// import AddIcon from '@material-ui/icons/Add'; +// import Typography from '@material-ui/core/Typography'; +// import { blue } from '@material-ui/core/colors'; + + + +function SimpleDialog(props) { + + const { onClose, selectedValue, open } = props; + + const handleClose = () => { + onClose(selectedValue); + }; + + const handleListItemClick = (value) => { + onClose(value); + }; + + return ( + + Set backup account + {/* + {emails.map((email) => ( + handleListItemClick(email)} key={email}> + + + + + + + + ))} + + handleListItemClick('addAccount')}> + + + + + + + + */} + + ); +} + +SimpleDialog.propTypes = { + onClose: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, + selectedValue: PropTypes.string.isRequired, +}; diff --git a/src/components/UI/FullScreenLoader/FullScreenLoader.tsx b/src/components/UI/FullScreenLoader/FullScreenLoader.tsx new file mode 100644 index 00000000..56c26878 --- /dev/null +++ b/src/components/UI/FullScreenLoader/FullScreenLoader.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Box, CircularProgress, Typography } from '@mui/material'; + +export const FullPageLoader: React.FC = () => { + return ( + + + + Prepping your data output... + + + ); +}; From 175528e9b5f3952934dc1c6ab2c46c6e5437f8d0 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Tue, 23 Jul 2024 19:01:28 +0530 Subject: [PATCH 04/52] added the overwrite component --- src/components/DataAnalysis/OverwriteBox.tsx | 96 +++++++++++++++++++ src/components/DataAnalysis/SavedSession.tsx | 1 - src/components/DataAnalysis/SqlWrite.tsx | 45 ++++++--- src/components/Dialog/DataDialog.tsx | 64 ------------- .../UI/FullScreenLoader/FullScreenLoader.tsx | 17 ++-- 5 files changed, 138 insertions(+), 85 deletions(-) create mode 100644 src/components/DataAnalysis/OverwriteBox.tsx delete mode 100644 src/components/Dialog/DataDialog.tsx diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx new file mode 100644 index 00000000..f23a5445 --- /dev/null +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -0,0 +1,96 @@ +import { Box, Button, TextField, Typography } from '@mui/material'; +import CloseIcon from '@/assets/icons/close_small.svg'; +import Image from 'next/image'; +export const OverWriteBox = () => { + return ( + <> + {/* main box */} + + {/* headings */} + info icon + + + + Overwrite Existing Session + + + The session with this name already exists. Do you want to + overwrite? + + + + {/* Input */} + + + + {/* final box */} + + + + + + + + + ); +}; diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx index ddd81d92..cacb68b4 100644 --- a/src/components/DataAnalysis/SavedSession.tsx +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -8,7 +8,6 @@ import { Paper, TableHead, TableRow, - Typography, Button, } from '@mui/material'; diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 9a7e68c2..2886e59e 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -1,12 +1,22 @@ -import { Box, Button, TextField, Typography } from '@mui/material'; +import { + Box, + Button, + CircularProgress, + TextField, + Typography, +} from '@mui/material'; import Image from 'next/image'; import SavedIcon from '@/assets/icons/folder.svg'; import InfoIcon from '@/assets/icons/info.svg'; import CloseIcon from '@/assets/icons/close_small.svg'; import { useState } from 'react'; import { SavedSession } from './SavedSession'; -import { FullPageLoader } from '../UI/FullScreenLoader/FullScreenLoader'; +import { FullPageBackground } from '../UI/FullScreenLoader/FullScreenLoader'; +import { OverWriteBox } from './OverwriteBox'; +const Areas_Of_Development= "Areas of Development"; +const Brightspots = "Brightspots"; +const Summarize = "Summarize"; export const SqlWrite = () => { const [customPromptToggle, setCustomPromptToggle] = useState(false); const [customPrompt, setCustomPrompt] = useState(''); @@ -17,6 +27,7 @@ export const SqlWrite = () => { const handleCloseSavedSession = () => { setOpenSavedSessionDialog(false); }; + const handlePromptSelection = (promptText: string) => { if (customPromptToggle) { setCustomPrompt(''); @@ -207,11 +218,11 @@ export const SqlWrite = () => { defaultPrompt === 'Brightspots' ? '#05443e' : '#00897B', }} onClick={() => { - handlePromptSelection('Brightspots'); + handlePromptSelection(Brightspots); }} > - Brightspots + {Brightspots}
@@ -326,7 +337,19 @@ export const SqlWrite = () => { open={openSavedSessionDialog} onClose={handleCloseSavedSession} /> - {loading&& } + {loading && ( + <> + + + {/* + + Prepping your data output... + */} + + + )} ); }; diff --git a/src/components/Dialog/DataDialog.tsx b/src/components/Dialog/DataDialog.tsx deleted file mode 100644 index 7f435434..00000000 --- a/src/components/Dialog/DataDialog.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Dialog, DialogTitle } from '@mui/material'; -// import { makeStyles } from '@material-ui/core/styles'; -// import Button from '@material-ui/core/Button'; -// import Avatar from '@material-ui/core/Avatar'; -// import List from '@material-ui/core/List'; -// import ListItem from '@material-ui/core/ListItem'; -// import ListItemAvatar from '@material-ui/core/ListItemAvatar'; -// import ListItemText from '@material-ui/core/ListItemText'; -// import DialogTitle from '@material-ui/core/DialogTitle'; -// import Dialog from '@material-ui/core/Dialog'; -// import PersonIcon from '@material-ui/icons/Person'; -// import AddIcon from '@material-ui/icons/Add'; -// import Typography from '@material-ui/core/Typography'; -// import { blue } from '@material-ui/core/colors'; - - - -function SimpleDialog(props) { - - const { onClose, selectedValue, open } = props; - - const handleClose = () => { - onClose(selectedValue); - }; - - const handleListItemClick = (value) => { - onClose(value); - }; - - return ( - - Set backup account - {/* - {emails.map((email) => ( - handleListItemClick(email)} key={email}> - - - - - - - - ))} - - handleListItemClick('addAccount')}> - - - - - - - - */} - - ); -} - -SimpleDialog.propTypes = { - onClose: PropTypes.func.isRequired, - open: PropTypes.bool.isRequired, - selectedValue: PropTypes.string.isRequired, -}; diff --git a/src/components/UI/FullScreenLoader/FullScreenLoader.tsx b/src/components/UI/FullScreenLoader/FullScreenLoader.tsx index 56c26878..a342fc61 100644 --- a/src/components/UI/FullScreenLoader/FullScreenLoader.tsx +++ b/src/components/UI/FullScreenLoader/FullScreenLoader.tsx @@ -1,11 +1,14 @@ import React from 'react'; -import { Box, CircularProgress, Typography } from '@mui/material'; +import { Box } from '@mui/material'; -export const FullPageLoader: React.FC = () => { +interface FullPageBackgroundProps { + children: React.ReactNode; +} + +export const FullPageBackground: React.FC = ({ children }) => { return ( { height: '100vh', backgroundColor: 'rgba(0, 0, 0, 0.8)', display: 'flex', - gap: "1rem", - flexDirection: "column", + flexDirection: 'column', justifyContent: 'center', alignItems: 'center', zIndex: 1300, }} > - - - Prepping your data output... - + {children} ); }; From 46d3955d8fab9e9949beebeaf99e1f7b64b43406 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Wed, 24 Jul 2024 08:11:57 +0530 Subject: [PATCH 05/52] added the remaining components --- src/components/DataAnalysis/ConfirmSaveAs.tsx | 84 ++++++++++++++++++ src/components/DataAnalysis/Feedback.tsx | 80 +++++++++++++++++ src/components/DataAnalysis/SqlWrite.tsx | 8 +- .../DataAnalysis/UnsavedChanges.tsx | 85 +++++++++++++++++++ 4 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 src/components/DataAnalysis/ConfirmSaveAs.tsx create mode 100644 src/components/DataAnalysis/Feedback.tsx create mode 100644 src/components/DataAnalysis/UnsavedChanges.tsx diff --git a/src/components/DataAnalysis/ConfirmSaveAs.tsx b/src/components/DataAnalysis/ConfirmSaveAs.tsx new file mode 100644 index 00000000..98b5bffd --- /dev/null +++ b/src/components/DataAnalysis/ConfirmSaveAs.tsx @@ -0,0 +1,84 @@ +import { Box, Button, TextField, Typography } from '@mui/material'; +import CloseIcon from '@/assets/icons/close_small.svg'; +import Image from 'next/image'; +export const ConfirmSaveAs = ()=>{ + return <> + + {/* main box */} + + {/* headings */} + info icon + + + + Confirm save as + + + Please rename the configuration before saving it in the warehouse + + + + {/* Input */} + + + + {/* final box */} + + + + + + + +} \ No newline at end of file diff --git a/src/components/DataAnalysis/Feedback.tsx b/src/components/DataAnalysis/Feedback.tsx new file mode 100644 index 00000000..3eb6390f --- /dev/null +++ b/src/components/DataAnalysis/Feedback.tsx @@ -0,0 +1,80 @@ +import { Box, Button, TextField, Typography } from '@mui/material'; +import CloseIcon from '@/assets/icons/close_small.svg'; +import Image from 'next/image'; +export const FeedBackForm = () => { + return ( + <> + {/* main box */} + + {/* headings */} + info icon + + + + Provide additional feedback + + + Tell us why this response was unsatisfactory{' '} + + + + {/* Input */} + + + + {/* final box */} + + + + + + + ); +}; diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 2886e59e..8bc5f3ac 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -13,6 +13,9 @@ import { useState } from 'react'; import { SavedSession } from './SavedSession'; import { FullPageBackground } from '../UI/FullScreenLoader/FullScreenLoader'; import { OverWriteBox } from './OverwriteBox'; +import { ConfirmSaveAs } from './ConfirmSaveAs'; +import { UnsavedChanges } from './UnsavedChanges'; +import { FeedBackForm } from './Feedback'; const Areas_Of_Development= "Areas of Development"; const Brightspots = "Brightspots"; @@ -340,7 +343,10 @@ export const SqlWrite = () => { {loading && ( <> - + {/* + */} + + {/* */} {/* { + return <> + + {/* main box */} + + {/* headings */} + info icon + + + + Unsaved changes + + + You are about to leave this page without saving the changes. + All the changes that were made will be lost. Do you wish to continue? + + + + {/* Input */} + + + + {/* final box */} + + + + + + + +} \ No newline at end of file From e4ff43006333fd65f4a8d123fdf100bdf1c8dec4 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Wed, 24 Jul 2024 16:34:06 +0530 Subject: [PATCH 06/52] connection log component test written --- src/components/Connections/ConnectionLogs.tsx | 4 +- .../__tests__/ConnectionLogs.test.tsx | 220 ++++++++++++++++++ 2 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 src/components/Connections/__tests__/ConnectionLogs.test.tsx diff --git a/src/components/Connections/ConnectionLogs.tsx b/src/components/Connections/ConnectionLogs.tsx index 77968ec8..676834bb 100644 --- a/src/components/Connections/ConnectionLogs.tsx +++ b/src/components/Connections/ConnectionLogs.tsx @@ -285,12 +285,12 @@ const Row = ({ onChange={handleAction} aria-label="text alignment" > - + Logs {allowLogsSummary && ( - + AI summary )} diff --git a/src/components/Connections/__tests__/ConnectionLogs.test.tsx b/src/components/Connections/__tests__/ConnectionLogs.test.tsx new file mode 100644 index 00000000..236d9b06 --- /dev/null +++ b/src/components/Connections/__tests__/ConnectionLogs.test.tsx @@ -0,0 +1,220 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { ConnectionLogs } from '../ConnectionLogs'; +import { GlobalContext } from '@/contexts/ContextProvider'; +import { useSession } from 'next-auth/react'; +import moment from 'moment'; + +// Mock useSession +jest.mock('next-auth/react', () => ({ + useSession: jest.fn(), +})); + +// Mock GlobalContext +const mockGlobalContext = { + state: {}, + dispatch: jest.fn(), +}; + +// Mock httpGet +jest.mock('../../../helpers/http', () => ({ + httpGet: jest.fn(), +})); + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const mockedHttpGet = require('../../../helpers/http').httpGet; + +// Sample connection data +const sampleConnection = { + connectionId: '123', + name: 'Test Connection', + source: { sourceName: 'Source A' }, + destination: { destinationName: 'Destination B' }, +}; + +// Sample log data +const sampleLogs = [ + { + attempt_no: 1, + bytesEmitted: '100MB', + date: moment().subtract(1, 'days').toISOString(), + job_id: 1, + logs: ['Log 1', 'Log 2'], + recordsCommitted: 1000, + recordsEmitted: 1000, + status: 'completed', + totalTimeInSeconds: 60, + }, + { + attempt_no: 2, + bytesEmitted: '200MB', + date: moment().subtract(1, 'days').toISOString(), + job_id: 1, + logs: ['Log 3', 'Log 4'], + recordsCommitted: 1000, + recordsEmitted: 1000, + status: 'completed', + totalTimeInSeconds: 60, + }, + { + attempt_no: 3, + bytesEmitted: '300MB', + date: moment().subtract(1, 'days').toISOString(), + job_id: 1, + logs: ['Log 5', 'Log 6'], + recordsCommitted: 1000, + recordsEmitted: 1000, + status: 'completed', + totalTimeInSeconds: 60, + }, + { + attempt_no: 4, + bytesEmitted: '400MB', + date: moment().subtract(1, 'days').toISOString(), + job_id: 1, + logs: ['Log 7', 'Log 8'], + recordsCommitted: 1000, + recordsEmitted: 1000, + status: 'completed', + totalTimeInSeconds: 60, + }, +]; + +// Mock useSession data +(useSession as jest.Mock).mockReturnValue({ + data: { user: { name: 'Test User' } }, +}); + +// Helper function to render component with context +const renderWithProviders = (ui: React.ReactElement) => { + return render( + + {ui} + + ); +}; + +describe('ConnectionLogs Component', () => { + beforeEach(() => { + mockedHttpGet.mockResolvedValue({ history: sampleLogs }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('renders the ConnectionLogs dialog', async () => { + renderWithProviders( + + ); + + expect(screen.getByText('Connection History')).toBeInTheDocument(); + expect(screen.getByText('Test Connection |')).toBeInTheDocument(); + expect(screen.getByText('Source A → Destination B')).toBeInTheDocument(); + + // Wait for data to load + await waitFor(() => expect(screen.getByText('100MB')).toBeInTheDocument()); + }); + + it('calls setShowLogsDialog on close button click', () => { + const setShowLogsDialog = jest.fn(); + renderWithProviders( + + ); + + fireEvent.click(screen.getByLabelText('close')); + expect(setShowLogsDialog).toHaveBeenCalledWith(false); + }); + + it('loads more logs when "load more" is clicked', async () => { + mockedHttpGet.mockResolvedValueOnce({ history: sampleLogs }); + renderWithProviders( + + ); + + await waitFor(() => + expect(screen.getByText('load more')).toBeInTheDocument() + ); + fireEvent.click(screen.getByText('load more')); + + await waitFor(() => expect(mockedHttpGet).toHaveBeenCalledTimes(2)); + }); + + it('displays no information message if no logs are available', async () => { + mockedHttpGet.mockResolvedValueOnce({ history: [] }); + renderWithProviders( + + ); + + await waitFor(() => + expect(screen.getByText('No information available')).toBeInTheDocument() + ); + }); + + it('renders AI summary when "AI summary" button is clicked', async () => { + renderWithProviders( + + ); + + await waitFor(() => expect(screen.getByText('100MB')).toBeInTheDocument()); + + const button = screen.getAllByTestId('aisummary-123'); + if (button.length) { + fireEvent.click(button[0]); + await waitFor(() => + expect(mockedHttpGet).toHaveBeenCalledWith( + expect.anything(), + `airbyte/v1/connections/123/logsummary?job_id=1&attempt_number=1` + ) + ); + } + }); + it('renders without crashing when no connection is provided', () => { + renderWithProviders( + + ); + + expect(screen.getByText('Connection History')).toBeInTheDocument(); + expect(screen.getByText('No information available')).toBeInTheDocument(); + }); + it('fetches and displays detailed logs when "Logs" button is clicked', async () => { + mockedHttpGet.mockResolvedValueOnce({ history: sampleLogs }); // For initial fetch + mockedHttpGet.mockResolvedValueOnce(['Detailed Log 1', 'Detailed Log 2']); // For detailed logs + + renderWithProviders( + + ); + + await waitFor(() => expect(screen.getByText('100MB')).toBeInTheDocument()); + const firstLabelTextButton = screen.getAllByTestId('logs'); + fireEvent.click(firstLabelTextButton[0]); + + await waitFor(() => + expect(mockedHttpGet).toHaveBeenCalledWith( + expect.anything(), + `airbyte/v1/logs?job_id=1&attempt_number=1` + ) + ); + + expect(screen.getByText('Detailed Log 1')).toBeInTheDocument(); + expect(screen.getByText('Detailed Log 2')).toBeInTheDocument(); + }); +}); From e48aac4387996ecbf1edaf3e209f76a7eb87214b Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Wed, 24 Jul 2024 18:52:51 +0530 Subject: [PATCH 07/52] Connection components test completed (schemachangedetection and connection logs) --- .../Connections/SchemaChangeDetailsForm.tsx | 5 +- .../SchemaChangeDetailsForm.test.tsx | 436 ++++++++++++++++++ 2 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 src/components/Connections/__tests__/SchemaChangeDetailsForm.test.tsx diff --git a/src/components/Connections/SchemaChangeDetailsForm.tsx b/src/components/Connections/SchemaChangeDetailsForm.tsx index c84b8168..3f6671a3 100644 --- a/src/components/Connections/SchemaChangeDetailsForm.tsx +++ b/src/components/Connections/SchemaChangeDetailsForm.tsx @@ -80,8 +80,9 @@ const SchemaChangeDetailsForm = ({ const checkProgress = async function ( taskId: string ): Promise<[boolean, any]> { + try { - const message = await httpGet(session, `tasks/stp/${taskId}`); + const message = await httpGet(session, `tasks/stp/${taskId}`) await delay(3000); setProgressMessages(message['progress']); const lastMessage = message['progress'][message['progress'].length - 1]; @@ -254,7 +255,6 @@ const SchemaChangeDetailsForm = ({ const FormContent = () => { const tableCount = tableData.length; - // Separate tables and columns added/removed const tablesRemoved = tableData.filter((table) => table.changedColumns.some((column) => column.startsWith('-Stream')) @@ -462,6 +462,7 @@ const SchemaChangeDetailsForm = ({ variant="contained" type="submit" disabled={hasBreakingChanges} + data-testid="approveschemachange" sx={{ marginTop: '20px' }} > Yes, I approve diff --git a/src/components/Connections/__tests__/SchemaChangeDetailsForm.test.tsx b/src/components/Connections/__tests__/SchemaChangeDetailsForm.test.tsx new file mode 100644 index 00000000..7ff88177 --- /dev/null +++ b/src/components/Connections/__tests__/SchemaChangeDetailsForm.test.tsx @@ -0,0 +1,436 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import SchemaChangeDetailsForm from '../SchemaChangeDetailsForm'; +import { GlobalContext } from '@/contexts/ContextProvider'; +import { useSession } from 'next-auth/react'; +// import CustomDialog from '../Dialog/CustomDialog'; +import { httpGet, httpPut } from '@/helpers/http'; +import { errorToast, successToast } from '../../ToastMessage/ToastHelper'; + +// Mock dependencies +jest.mock('next-auth/react'); +jest.mock('../../../helpers/http'); +jest.mock('../../ToastMessage/ToastHelper'); +const nonBreakingData = { + progress: [ + { + message: 'started', + status: 'running', + }, + { + message: 'fetched catalog data', + status: 'completed', + result: { + name: 'Worldometer', + connectionId: '1ff9f64f-fc97-4358-8b8a-59cfa2432479', + catalogId: '76e1f022-a049-4ab0-b5f6-7a34c46cb82c', + syncCatalog: { + streams: [ + { + stream: { + name: 'worldometer_data', + jsonSchema: { + type: 'object', + properties: { + 'New column of nulls': { type: 'string' }, + 'Second new column': { type: 'string' }, + }, + }, + }, + config: { + syncMode: 'full_refresh', + destinationSyncMode: 'overwrite', + aliasName: 'worldometer_data', + selected: true, + }, + }, + { + stream: { + name: 'new_tab', + jsonSchema: { + type: 'object', + properties: { + A: { type: 'string' }, + b: { type: 'string' }, + }, + }, + }, + config: { + syncMode: 'full_refresh', + destinationSyncMode: 'overwrite', + aliasName: 'new_tab', + selected: false, + }, + }, + ], + }, + schemaChange: 'non_breaking', + catalogDiff: { + transforms: [ + { + transformType: 'add_stream', + streamDescriptor: { + name: 'new_tab', + }, + }, + { + transformType: 'update_stream', + streamDescriptor: { + name: 'worldometer_data', + }, + updateStream: [ + { + transformType: 'add_field', + fieldName: ['Second new column'], + breaking: false, + }, + { + transformType: 'add_field', + fieldName: ['New column of nulls'], + breaking: false, + }, + ], + }, + ], + }, + }, + }, + ], + } +describe('SchemaChangeDetailsForm', () => { + const mockMutate = jest.fn(); + const mockSetShowForm = jest.fn(); + const mockSetConnectionId = jest.fn(); + const mockFetchPendingActions = jest.fn(); + const mockSession = { data: { token: 'mockToken' } }; + + const defaultProps = { + connectionId: 'test-connection-id', + mutate: mockMutate, + showForm: true, + setShowForm: mockSetShowForm, + setConnectionId: mockSetConnectionId, + fetchPendingActions: mockFetchPendingActions, + }; + + const mockContextValue = { + someContextValue: 'test-value', + }; + + beforeEach(() => { + jest.clearAllMocks(); + useSession.mockReturnValue(mockSession); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + it('renders the component and fetches data on load', async () => { + jest.useFakeTimers(); // Use fake timers + + httpGet.mockResolvedValueOnce({ + task_id: 'mock-task-id', + }); + + httpGet.mockResolvedValueOnce({ + progress: [ + { + status: 'completed', + result: { + catalogId: 'mock-catalog-id', + name: 'mock-name', + syncCatalog: { streams: [] }, + }, + }, + ], + }); + + render( + + + + ); + + expect(screen.getByText('New Schema Changes Detected')).toBeInTheDocument(); + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(1)); + + // Fast-forward time by 3 seconds + jest.advanceTimersByTime(3000); + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(2)); + + await waitFor(() => + expect( + screen.getByText('New Schema Changes Detected') + ).toBeInTheDocument() + ); + + jest.useRealTimers(); // Restore real timers + }); + + it('handles form submission successfully', async () => { + jest.useFakeTimers(); // Use fake timers + httpGet.mockResolvedValueOnce({ + task_id: 'mock-task-id', + }); + + httpGet.mockResolvedValueOnce(nonBreakingData); + + httpPut.mockResolvedValueOnce({}); + + render( + + + + ); + + // Ensure data is fetched and rendered + expect(screen.getByText('New Schema Changes Detected')).toBeInTheDocument(); + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(1)); + + jest.advanceTimersByTime(3000); // Fast-forward time by 3 seconds + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(2)); + jest.advanceTimersByTime(3000); + // Verify the presence of table changes + await waitFor(() => + expect(screen.getByText('2 tables with changes')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Tables Added')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('new_tab')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('New column of nulls')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Second new column')).toBeInTheDocument() + ); + + // Submit the form + fireEvent.click(screen.getByText('Yes, I approve')); + + await waitFor(() => expect(httpPut).toHaveBeenCalledTimes(1)); + await waitFor(() => + expect(successToast).toHaveBeenCalledWith( + 'Connection updated', + [], + mockContextValue + ) + ); + jest.useRealTimers(); // Restore real timers + }); + + it('handles form submission failure', async () => { + jest.useFakeTimers(); // Use fake timers + httpGet.mockResolvedValueOnce({ + task_id: 'mock-task-id', + }); + + httpGet.mockResolvedValueOnce(nonBreakingData); + + httpPut.mockResolvedValueOnce({}); + + render( + + + + ); + + // Ensure data is fetched and rendered + expect(screen.getByText('New Schema Changes Detected')).toBeInTheDocument(); + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(1)); + + jest.advanceTimersByTime(3000); // Fast-forward time by 3 seconds + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(2)); + jest.advanceTimersByTime(3000); + // Verify the presence of table changes + await waitFor(() => + expect(screen.getByText('2 tables with changes')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Tables Added')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('new_tab')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('New column of nulls')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Second new column')).toBeInTheDocument() + ); + + // Submit the form + fireEvent.click(screen.getByText('Yes, I approve')); + const mockError = new Error('Submission failed'); + httpPut.mockRejectedValueOnce(mockError); + + render( + + + + ); + + fireEvent.click(screen.getByTestId('approveschemachange')); + + await waitFor(() => expect(httpPut).toHaveBeenCalledTimes(2)); + await waitFor(() => + expect(errorToast).toHaveBeenCalledWith( + mockError.message, + [], + mockContextValue + ) + ); + jest.useRealTimers(); + }); + + it('handles closing the dialog', () => { + render( + + + + ); + + fireEvent.click(screen.getByText('Close')); + expect(mockSetShowForm).toHaveBeenCalledWith(false); + }); + + it('disables the submit button if there are breaking changes', async () => { + jest.useFakeTimers(); // Use fake timers + httpGet.mockResolvedValueOnce({ + task_id: 'mock-task-id', + }); + + httpGet.mockResolvedValueOnce({ + progress: [ + { + message: 'started', + status: 'running', + }, + { + message: 'fetched catalog data', + status: 'completed', + result: { + name: 'Worldometer', + connectionId: '1ff9f64f-fc97-4358-8b8a-59cfa2432479', + catalogId: '76e1f022-a049-4ab0-b5f6-7a34c46cb82c', + syncCatalog: { + streams: [ + { + stream: { + name: 'worldometer_data', + jsonSchema: { + type: 'object', + properties: { + 'New column of nulls': { type: 'string' }, + 'Second new column': { type: 'string' }, + }, + }, + }, + config: { + syncMode: 'full_refresh', + destinationSyncMode: 'overwrite', + aliasName: 'worldometer_data', + selected: true, + }, + }, + { + stream: { + name: 'new_tab', + jsonSchema: { + type: 'object', + properties: { + A: { type: 'string' }, + b: { type: 'string' }, + }, + }, + }, + config: { + syncMode: 'full_refresh', + destinationSyncMode: 'overwrite', + aliasName: 'new_tab', + selected: false, + }, + }, + ], + }, + schemaChange: 'breaking', + catalogDiff: { + transforms: [ + { + transformType: 'add_stream', + streamDescriptor: { + name: 'new_tab', + }, + }, + { + transformType: 'update_stream', + streamDescriptor: { + name: 'worldometer_data', + }, + updateStream: [ + { + transformType: 'add_field', + fieldName: ['Second new column'], + breaking: false, + }, + { + transformType: 'add_field', + fieldName: ['New column of nulls'], + breaking: false, + }, + ], + }, + ], + }, + }, + }, + ], + }); + + httpPut.mockResolvedValueOnce({}); + + render( + + + + ); + + // Ensure data is fetched and rendered + expect(screen.getByText('New Schema Changes Detected')).toBeInTheDocument(); + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(1)); + + jest.advanceTimersByTime(3000); // Fast-forward time by 3 seconds + + await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(2)); + jest.advanceTimersByTime(3000); + // Verify the presence of table changes + await waitFor(() => + expect(screen.getByText('2 tables with changes')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Tables Added')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('new_tab')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('New column of nulls')).toBeInTheDocument() + ); + await waitFor(() => + expect(screen.getByText('Second new column')).toBeInTheDocument() + ); + + await waitFor(() => + expect(screen.getByTestId('approveschemachange')).toBeDisabled() + ); + }); +}); From f415abb4a713681c3ce6d5dcad1256dcc0d5db47 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Sat, 27 Jul 2024 16:18:04 +0530 Subject: [PATCH 08/52] fixed the css --- src/components/DataAnalysis/SqlWrite.tsx | 21 +++++++++++---------- src/config/menu.tsx | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 8bc5f3ac..5dfafe40 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -101,8 +101,8 @@ export const SqlWrite = () => { fontSize: '14px', alignItems: 'center', justifyContent: 'center', - padding: '0.5rem', flexGrow: 1, + height: "2rem" }} onClick={() => { setOpenSavedSessionDialog(true); @@ -119,7 +119,8 @@ export const SqlWrite = () => { ))} + + + + setCurrentPageIndex(newPage + 1)} + onRowsPerPageChange={(e: any) => { + setPageSize(e.target.value); + setCurrentPageIndex(1); + }} + />
diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 5dfafe40..bc13a053 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -1,7 +1,6 @@ import { Box, Button, - CircularProgress, TextField, Typography, } from '@mui/material'; @@ -9,24 +8,23 @@ import Image from 'next/image'; import SavedIcon from '@/assets/icons/folder.svg'; import InfoIcon from '@/assets/icons/info.svg'; import CloseIcon from '@/assets/icons/close_small.svg'; -import { useState } from 'react'; +import { useContext, useState } from 'react'; import { SavedSession } from './SavedSession'; -import { FullPageBackground } from '../UI/FullScreenLoader/FullScreenLoader'; -import { OverWriteBox } from './OverwriteBox'; -import { ConfirmSaveAs } from './ConfirmSaveAs'; -import { UnsavedChanges } from './UnsavedChanges'; -import { FeedBackForm } from './Feedback'; +import { GlobalContext } from '@/contexts/ContextProvider'; +import { errorToast } from '../ToastMessage/ToastHelper'; -const Areas_Of_Development= "Areas of Development"; -const Brightspots = "Brightspots"; -const Summarize = "Summarize"; -export const SqlWrite = () => { + +const Areas_Of_Development = 'Areas of Development'; +const Brightspots = 'Brightspots'; +const Summarize = 'Summarize'; + +export const SqlWrite = ({ getLLMSummary }: { getLLMSummary: any }) => { const [customPromptToggle, setCustomPromptToggle] = useState(false); const [customPrompt, setCustomPrompt] = useState(''); const [defaultPrompt, setDefaultPrompt] = useState(''); const [sqlText, setSqlText] = useState(''); - const [loading, setLoading] = useState(false); const [openSavedSessionDialog, setOpenSavedSessionDialog] = useState(false); + const globalContext = useContext(GlobalContext); const handleCloseSavedSession = () => { setOpenSavedSessionDialog(false); }; @@ -38,14 +36,24 @@ export const SqlWrite = () => { } setDefaultPrompt(promptText); }; - const handleSubmit = () => { - if ((sqlText && customPrompt) || (sqlText && defaultPrompt)) { - //api call - setLoading(true); - setTimeout(() => { - setLoading(false); - }, 2000); + + const handleSubmit = async () => { + if (!sqlText) { + errorToast('Please enter a SELECT sql query', [], globalContext); + return; + } + if (!customPrompt && !defaultPrompt) { + errorToast( + 'Either select a default prompt or write a custom prompt', + [], + globalContext + ); + return; } + getLLMSummary({ + sqlText, + user_prompt: customPrompt || defaultPrompt, + }); }; return ( <> @@ -102,7 +110,7 @@ export const SqlWrite = () => { alignItems: 'center', justifyContent: 'center', flexGrow: 1, - height: "2rem" + height: '2rem', }} onClick={() => { setOpenSavedSessionDialog(true); @@ -119,8 +127,7 @@ export const SqlWrite = () => {
+ {isBoxOpen && ( + + )} ); diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index f23a5445..09d350a7 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -1,96 +1,107 @@ -import { Box, Button, TextField, Typography } from '@mui/material'; -import CloseIcon from '@/assets/icons/close_small.svg'; +import React, { useState } from 'react'; +import { + Box, + Button, + TextField, + Typography, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, +} from '@mui/material'; import Image from 'next/image'; -export const OverWriteBox = () => { +import CloseIcon from '@/assets/icons/close_small.svg'; + +export const OverWriteDialog = ({ open, setIsBoxOpen, sessionName }: { open: boolean, sessionName: string, setIsBoxOpen: (a: boolean) => void }) => { + const [newSessionName, setNewSessionName] = useState(sessionName); + const handleClose = () => (setIsBoxOpen(false)); return ( <> - {/* main box */} - - {/* headings */} - info icon - - + {/* Dialog Box */} + + {/* Dialog Title with close button */} + + Overwrite Existing Session - - The session with this name already exists. Do you want to - overwrite? - + Close + + - {/* Input */} - - - - {/* final box */} - + - - - + value={newSessionName} + onChange={(e) => { setNewSessionName(e.target.value) }} + /> - - + + + {/* Dialog Actions */} + + + + + + ); }; + + diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index bc13a053..bcc7b610 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -18,7 +18,7 @@ const Areas_Of_Development = 'Areas of Development'; const Brightspots = 'Brightspots'; const Summarize = 'Summarize'; -export const SqlWrite = ({ getLLMSummary }: { getLLMSummary: any }) => { +export const SqlWrite = ({ getLLMSummary, prompt, sessionId, loading }: { getLLMSummary: any, prompt: string, sessionId: string, loading:boolean }) => { const [customPromptToggle, setCustomPromptToggle] = useState(false); const [customPrompt, setCustomPrompt] = useState(''); const [defaultPrompt, setDefaultPrompt] = useState(''); @@ -329,6 +329,7 @@ export const SqlWrite = ({ getLLMSummary }: { getLLMSummary: any }) => { onClick={() => { handleSubmit(); }} + // disabled={sessionId ? true: false} variant="contained" sx={{ width: '6.75rem', @@ -345,7 +346,7 @@ export const SqlWrite = ({ getLLMSummary }: { getLLMSummary: any }) => { + /> ); }; diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index 1a00fa2c..12fcc8ff 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -12,10 +12,15 @@ import { } from '@/components/ToastMessage/ToastHelper'; import { useContext, useState } from 'react'; import { FullPageBackground } from '@/components/UI/FullScreenLoader/FullScreenLoader'; +import { useLockCanvas } from '@/customHooks/useLockCanvas'; export default function DataAnalysis() { const { data: session } = useSession(); - const [llmSummary, setllmSummary] = useState(''); + const [{ prompt, summary, sessionId }, setllmSummaryResult] = useState({ + prompt: "", + summary: "", + sessionId: "" + }); const globalContext = useContext(GlobalContext); const [loading, setLoading] = useState(false); @@ -25,14 +30,21 @@ export default function DataAnalysis() { const response: any = await httpGet(session, 'tasks/stp/' + taskId); const lastMessage: any = response['progress'][response['progress'].length - 1]; - if (!['completed', 'failed'].includes(lastMessage.status)) { await delay(3000); await pollForTaskRun(taskId); - } else if(['failed'].includes(lastMessage.status)){ + } + + else if (['failed'].includes(lastMessage.status)) { errorToast(lastMessage.message, [], globalContext); - } else{ - setllmSummary(lastMessage.result); + return; + } else { + successToast(lastMessage.message, [], globalContext); + setllmSummaryResult({ + prompt: lastMessage?.result?.response[0]?.prompt, + summary: lastMessage?.result?.response[0].response, + sessionId: lastMessage?.result?.session_id + }); } } catch (err: any) { console.error(err); @@ -53,7 +65,7 @@ export default function DataAnalysis() { try { const response = await httpPost(session, `warehouse/ask/`, { sql: sqlText, - session_name: `unique-${Date.now()}`, + // session_name: `unique-${Date.now()}`, user_prompt, }); console.log(response, 'taskid'); @@ -61,20 +73,19 @@ export default function DataAnalysis() { errorToast(response.detail, [], globalContext); return { error: 'ERROR' }; } - if (!response?.task_id) { + if (!response?.request_uuid) { errorToast('Something went wrong', [], globalContext); return { error: 'ERROR' }; } successToast(`Data analysis initiated successfully`, [], globalContext); await delay(3000); - pollForTaskRun(response.task_id); + pollForTaskRun(response.request_uuid); } catch (err: any) { console.error(err); - errorToast(err.message, [], globalContext); - } finally { setLoading(false); - } + errorToast(err.message, [], globalContext); + } }; return ( @@ -88,9 +99,9 @@ export default function DataAnalysis() { }} > {/* Sql filter */} - + {/* LLM summary */} - + {loading && ( <> From f8c7d9f654a73c3cd8540057e2bf092e05aeb4c7 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Wed, 4 Sep 2024 20:24:09 +0530 Subject: [PATCH 12/52] added the api to save session, refactored some components --- src/components/DataAnalysis/LLMSummary.tsx | 11 +- src/components/DataAnalysis/OverwriteBox.tsx | 155 ++++++++++++++----- src/pages/analysis/data-analysis.tsx | 3 +- 3 files changed, 120 insertions(+), 49 deletions(-) diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index 9c379e12..2334bbc7 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -1,4 +1,4 @@ -import { Backdrop, Box, Button, Typography } from '@mui/material'; +import { Box, Button, Typography } from '@mui/material'; import Image from 'next/image'; import InfoIcon from '@/assets/icons/info.svg'; import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; @@ -6,13 +6,12 @@ import CopyIcon from '@/assets/icons/content_copy.svg'; import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; import { memo, useState } from 'react'; -import { httpPost } from '@/helpers/http'; import { OverWriteDialog } from './OverwriteBox'; -import { FullPageBackground } from '../UI/FullScreenLoader/FullScreenLoader'; -export const LLMSummary = memo(({ llmSummary, sessionId , prompt }: { llmSummary: string, sessionId: string, prompt: string }) => { +export const LLMSummary = memo(({ llmSummary, oldSessionId, newSessionId , prompt }: { llmSummary: string, oldSessionId: string, newSessionId: string , prompt: string }) => { const [isBoxOpen, setIsBoxOpen] = useState(false); - const sessionName = prompt ?`${prompt}_${Date.now()}` : ""; + const sessionName = `${prompt}_${Date.now()}`; + const modalName = oldSessionId ? "OVERWRITE": "SAVE" return ( <> @@ -121,7 +120,7 @@ export const LLMSummary = memo(({ llmSummary, sessionId , prompt }: { llmSummary {isBoxOpen && ( - + )} diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 09d350a7..77ce6738 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useContext, useState } from 'react'; import { Box, Button, @@ -12,10 +12,106 @@ import { } from '@mui/material'; import Image from 'next/image'; import CloseIcon from '@/assets/icons/close_small.svg'; +import { httpPost } from '@/helpers/http'; +import { useSession } from 'next-auth/react'; +import { errorToast, successToast } from '../ToastMessage/ToastHelper'; +import { GlobalContext } from '@/contexts/ContextProvider'; -export const OverWriteDialog = ({ open, setIsBoxOpen, sessionName }: { open: boolean, sessionName: string, setIsBoxOpen: (a: boolean) => void }) => { - const [newSessionName, setNewSessionName] = useState(sessionName); +export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,oldSessionId, newSessionId }: { open: boolean, session_name: string, modalName: string, oldSessionId: string, newSessionId:string,setIsBoxOpen: (a: boolean) => void }) => { + const {data:session} = useSession(); + const globalContext = useContext(GlobalContext); + const [sessionName, setSessionName] = useState(session_name); const handleClose = () => (setIsBoxOpen(false)); + + const handleSaveSession =async(overwrite:boolean, old_session_id:string | null)=>{ + try { + const response = await httpPost(session, `warehouse/ask/${newSessionId}/save`, { + "session_name": sessionName, + overwrite, + old_session_id + }); + console.log(response, "response"); + //write error condition + if(response.success){ + successToast(`${sessionName} saved successfully`, [], globalContext); + } + + } catch (err:any) { + console.log(err); + errorToast(err.message, [], globalContext); + } + } + const ModalData: any = { + SAVE: { + mainheading: "Save as", + subHeading: "Please name the configuration before saving it in the warehouse", + buttons: [{ + label: 'Save', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(false, null) + }, + }, { + label: 'Cancel', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, + },] + }, + OVERWRITE: { + mainheading: "Overwrite existing session", + subHeading: "The session with this name already exists. Do you want to overwrite?", + buttons: [ + { + label: 'Overwrite', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(true, oldSessionId) + }, + }, + { + label: 'Save as new', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + console.log('Save as new clicked'); + }, + }, + { + label: 'Cancel', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, // Use existing handleClose function for the Cancel button + },] + }, + UNSAVED_CHANGES: { + mainheading: "", + subHeading: "", + buttons: [{}, {}] + } + } return ( <> {/* Dialog Box */} @@ -26,7 +122,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, sessionName }: { open: boo - Overwrite Existing Session + {ModalData[modalName].mainheading} - The session with this name already exists. Do you want to overwrite? + {ModalData[modalName].subHeading} {/* Input Field */} @@ -57,47 +153,24 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, sessionName }: { open: boo fullWidth label="Session Name" variant="outlined" - value={newSessionName} - onChange={(e) => { setNewSessionName(e.target.value) }} + value={sessionName} + onChange={(e) => { setSessionName(e.target.value) }} /> {/* Dialog Actions */} - - - - + + {ModalData[modalName].buttons.map((button: any, index: number) => ( + + ))} diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index 12fcc8ff..1a9b110b 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -12,7 +12,6 @@ import { } from '@/components/ToastMessage/ToastHelper'; import { useContext, useState } from 'react'; import { FullPageBackground } from '@/components/UI/FullScreenLoader/FullScreenLoader'; -import { useLockCanvas } from '@/customHooks/useLockCanvas'; export default function DataAnalysis() { const { data: session } = useSession(); @@ -101,7 +100,7 @@ export default function DataAnalysis() { {/* Sql filter */} {/* LLM summary */} - + {loading && ( <> From 3da1c2de39ff649a2d3fea9607f6bd3f438e576f Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Thu, 5 Sep 2024 02:27:47 +0530 Subject: [PATCH 13/52] chnaged the structure of the components, removed the saveed session from sql write to main component --- src/components/DataAnalysis/LLMSummary.tsx | 15 +- src/components/DataAnalysis/SavedSession.tsx | 110 ++--- src/components/DataAnalysis/SqlWrite.tsx | 453 ++++++++----------- src/components/DataAnalysis/TopBar.tsx | 80 ++++ src/pages/analysis/data-analysis.tsx | 99 +++- 5 files changed, 388 insertions(+), 369 deletions(-) create mode 100644 src/components/DataAnalysis/TopBar.tsx diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index 2334bbc7..0a599432 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -6,12 +6,13 @@ import CopyIcon from '@/assets/icons/content_copy.svg'; import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; import { memo, useState } from 'react'; -import { OverWriteDialog } from './OverwriteBox'; +import { OverWriteDialog } from './OverwriteBox'; -export const LLMSummary = memo(({ llmSummary, oldSessionId, newSessionId , prompt }: { llmSummary: string, oldSessionId: string, newSessionId: string , prompt: string }) => { - const [isBoxOpen, setIsBoxOpen] = useState(false); +export const LLMSummary = memo(({ llmSummary, newSessionId, prompt, oldSessionMetaInfo }: { llmSummary: string, newSessionId: string, prompt: string, oldSessionMetaInfo: any }) => { + const [isBoxOpen, setIsBoxOpen] = useState(false); const sessionName = `${prompt}_${Date.now()}`; - const modalName = oldSessionId ? "OVERWRITE": "SAVE" + const modalName = oldSessionMetaInfo.oldSessionId ? "OVERWRITE" : "SAVE" + console.log("hello") return ( <> @@ -93,7 +94,7 @@ export const LLMSummary = memo(({ llmSummary, oldSessionId, newSessionId , promp {isBoxOpen && ( - + )} diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx index db89d516..e1bc426b 100644 --- a/src/components/DataAnalysis/SavedSession.tsx +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -16,79 +16,29 @@ import Image from 'next/image'; import InfoIcon from '@/assets/icons/info.svg'; import CloseIcon from "@/assets/icons/close_small.svg"; import ArrowIcon from "@/assets/icons/arrow_back_ios.svg" -import { useState } from 'react'; +import { useEffect, useState } from 'react'; +import { httpGet } from '@/helpers/http'; +import { useSession } from 'next-auth/react'; -const dataArray = [ - { - sno: 1, - createdOn: '2024-07-01', - updatedOn: '2024-07-02', - name: 'John Doe', - createdBy: 'admin@example.com', - }, - { - sno: 2, - createdOn: '2024-07-02', - updatedOn: '2024-07-03', - name: 'Jane Smith', - createdBy: 'admin@example.com', - }, - { - sno: 3, - createdOn: '2024-07-03', - updatedOn: '2024-07-04', - name: 'Alice Johnson', - createdBy: 'moderator@example.com', - }, - { - sno: 4, - createdOn: '2024-07-04', - updatedOn: '2024-07-05', - name: 'Bob Brown', - createdBy: 'admin@example.com', - }, - { - sno: 5, - createdOn: '2024-07-05', - updatedOn: '2024-07-06', - name: 'Charlie Davis', - createdBy: 'user@example.com', - }, - { - sno: 6, - createdOn: '2024-07-04', - updatedOn: '2024-07-05', - name: 'Bob Brown', - createdBy: 'admin@example.com', - }, - { - sno: 7, - createdOn: '2024-07-05', - updatedOn: '2024-07-06', - name: 'Charlie Davis', - createdBy: 'user@example.com', - }, - { - sno: 8, - createdOn: '2024-07-04', - updatedOn: '2024-07-05', - name: 'Bob Brown', - createdBy: 'admin@example.com', - }, - { - sno: 9, - createdOn: '2024-07-05', - updatedOn: '2024-07-06', - name: 'Charlie Davis', - createdBy: 'user@example.com', - }, -]; -export const SavedSession = ({ open, onClose }: { open: boolean, onClose: any }) => { - const [pageSize, setPageSize] = useState(5); + +export const SavedSession = ({ open, onClose, handleEditSession }: { open: boolean, onClose: any, handleEditSession:any }) => { + const {data: session} = useSession(); + const [pageSize, setPageSize] = useState(0); const [totalCount, setTotalCount] = useState(0); // Total count of rows const [pageCount, setPageCount] = useState(0); // Total number of pages const [currentPageIndex, setCurrentPageIndex] = useState(1); // Page index + const [savedSessions, setSavedSession] = useState([]); + + useEffect(()=>{ + const getSavedSessions = async ()=>{ + const response = await httpGet(session, `warehouse/ask/sessions?limit=${10}&offset=${pageSize}`); + console.log(response, "response"); + setSavedSession(response) + } + getSavedSessions(); + },[session]) + return ( <> - {dataArray.map((row) => ( + {savedSessions.map((row:any, idx) => ( - {row.sno} + {idx} - {row.name} + {row.session_name} { + handleEditSession({ + prompt: row.response[0].prompt, + summary: row?.response[0]?.response, + oldSessionId: row.session_id, + session_status: row.session_status, + session_name: row.session_name, + sqlText: row?.request_meta?.sql, + taskId: row.request_uuid + }); + console.log(row.request_meta.sql, "meta") + onClose(); + } + + } > OPEN close icon @@ -305,7 +270,6 @@ export const SavedSession = ({ open, onClose }: { open: boolean, onClose: any }) - { +export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSessionMetaInfo }: { getLLMSummary: any, prompt: string, loading: boolean, oldSessionMetaInfo: any, newSessionId: string }) => { + const { data: session } = useSession(); + const [defaultPromptsLists, setDefaultPromptLists] = useState([]); const [customPromptToggle, setCustomPromptToggle] = useState(false); - const [customPrompt, setCustomPrompt] = useState(''); - const [defaultPrompt, setDefaultPrompt] = useState(''); - const [sqlText, setSqlText] = useState(''); - const [openSavedSessionDialog, setOpenSavedSessionDialog] = useState(false); + const [customPrompt, setCustomPrompt] = useState(""); + const [defaultPrompt, setDefaultPrompt] = useState(""); + const [sqlText, setSqlText] = useState(""); const globalContext = useContext(GlobalContext); - const handleCloseSavedSession = () => { - setOpenSavedSessionDialog(false); - }; + const handlePromptSelection = (promptText: string) => { if (customPromptToggle) { @@ -55,307 +52,217 @@ export const SqlWrite = ({ getLLMSummary, prompt, sessionId, loading }: { getLLM user_prompt: customPrompt || defaultPrompt, }); }; + + + useEffect(() => { + console.log("hellooooooooooooooooooooooooooo") + try { + const getDefaultPrompts = async () => { + const response = await httpGet(session, `data/user_prompts/`); + console.log(response, "response"); + if (response.length) { + const isDefaultPrompt = response.some((item: any) => { + return item?.prompt === prompt; + }); + + console.log(isDefaultPrompt, "isdeafult") + setCustomPromptToggle(isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true); + setCustomPrompt(isDefaultPrompt ? "" : prompt); + setDefaultPrompt(isDefaultPrompt ? prompt : ""); + setSqlText(oldSessionMetaInfo?.sqlText || ""); + } + + setDefaultPromptLists(response) + } + if (session) { + getDefaultPrompts(); + } + } catch (error) { + console.log(error) + } + }, [session, oldSessionMetaInfo.sqlText]) + return ( <> - - + + {/* second box */} + +
+
+ {/* Third box with sql editor */} + + + + SQL Filter* + + + {/* This contains the sql filter */} + { + setSqlText(e.target.value); + }} + /> + + + {/* foruth box with some buttons */} + - Parameters - logout icon - - - - - - + (Choose any one from the given prompts) + - {/* second box */} - -
-
- {/* Third box with sql editor */} - - - SQL Filter* - - - {/* This contains the sql filter */} - { - setSqlText(e.target.value); - }} - /> - - - {/* foruth box with some buttons */} - - - { + return ( + + ) + })} + - - - - - - - - OR - - - {customPromptToggle ? ( - - - Custom Prompt - { - setCustomPromptToggle(false); - setCustomPrompt(''); - }} - alt="close icon" - /> - - { - setCustomPrompt(e.target.value); + Custom Prompt + { + setCustomPromptToggle(false); + setCustomPrompt(''); }} + alt="close icon" /> - ) : ( - - )} - - + /> + + ) : ( + + )}
+
- ); }; -const customCss = { - display: 'flex', - boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', - backgroundColor: '#FFFFFF', - borderRadius: '12px', - padding: '2rem', - // borderColor: '#FFFFFF', -}; + diff --git a/src/components/DataAnalysis/TopBar.tsx b/src/components/DataAnalysis/TopBar.tsx new file mode 100644 index 00000000..3bca6c4a --- /dev/null +++ b/src/components/DataAnalysis/TopBar.tsx @@ -0,0 +1,80 @@ +import { Box, Button, Typography } from "@mui/material"; +import Image from "next/image"; +import SavedIcon from '@/assets/icons/folder.svg'; +import InfoIcon from '@/assets/icons/info.svg'; +export const TopBar = ({handleOpenSavedSession}:any) => { + return <> + + + Parameters + logout icon + + + + + + + + + + +} + diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index 1a9b110b..f7a0c76f 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -1,27 +1,54 @@ -import { Box, CircularProgress, Typography } from '@mui/material'; - +import { Box, Button, CircularProgress, Typography } from '@mui/material'; import { LLMSummary } from '@/components/DataAnalysis/LLMSummary'; import { SqlWrite } from '@/components/DataAnalysis/SqlWrite'; import { httpGet, httpPost } from '@/helpers/http'; import { useSession } from 'next-auth/react'; import { delay } from '@/utils/common'; import { GlobalContext } from '@/contexts/ContextProvider'; + import { errorToast, successToast, } from '@/components/ToastMessage/ToastHelper'; -import { useContext, useState } from 'react'; +import { useContext, useEffect, useState } from 'react'; import { FullPageBackground } from '@/components/UI/FullScreenLoader/FullScreenLoader'; +import { SavedSession } from '@/components/DataAnalysis/SavedSession'; +import { TopBar } from '@/components/DataAnalysis/TopBar'; export default function DataAnalysis() { const { data: session } = useSession(); - const [{ prompt, summary, sessionId }, setllmSummaryResult] = useState({ + const [{ prompt, summary, newSessionId }, setllmSummaryResult] = useState({ prompt: "", summary: "", - sessionId: "" + newSessionId: "", }); + const globalContext = useContext(GlobalContext); const [loading, setLoading] = useState(false); + const [openSavedSessionDialog, setOpenSavedSessionDialog] = useState(false); + const [oldSessionMetaInfo, setOldSessionMetaInfo] = useState({ + session_status: "", + sqlText: "", + taskId: "", + session_name: "", + oldSessionId: "", + }); + const handleCloseSavedSession = () => { + setOpenSavedSessionDialog(false); + }; + const handleOpenSavedSession = () => { + setOpenSavedSessionDialog(true); + } + const handleEditSession = (info: any) => { + setOldSessionMetaInfo({ + ...oldSessionMetaInfo, ...info + }) + setllmSummaryResult({ + prompt: info.prompt, + summary: info.summary, + newSessionId: "" + }) + } //polling const pollForTaskRun = async (taskId: string) => { @@ -39,10 +66,9 @@ export default function DataAnalysis() { return; } else { successToast(lastMessage.message, [], globalContext); - setllmSummaryResult({ - prompt: lastMessage?.result?.response[0]?.prompt, - summary: lastMessage?.result?.response[0].response, - sessionId: lastMessage?.result?.session_id + setllmSummaryResult((prev)=>{ + return {...prev, summary: lastMessage?.result?.response[0].response, + newSessionId: lastMessage?.result?.session_id} }); } } catch (err: any) { @@ -64,7 +90,6 @@ export default function DataAnalysis() { try { const response = await httpPost(session, `warehouse/ask/`, { sql: sqlText, - // session_name: `unique-${Date.now()}`, user_prompt, }); console.log(response, 'taskid'); @@ -84,9 +109,11 @@ export default function DataAnalysis() { console.error(err); setLoading(false); errorToast(err.message, [], globalContext); - } + } }; + + return ( <> - {/* Sql filter */} - - {/* LLM summary */} - + + {/* Top saved Session Option */} + + + {/* SQL write Area */} + + + + {/* Final Summary */} + + + {/* Loader full screen */} {loading && ( <> @@ -113,7 +164,23 @@ export default function DataAnalysis() { )} + + {/* Saved Session Dailog */} + {openSavedSessionDialog && } ); -} \ No newline at end of file +} + +const customCss = { + display: 'flex', + boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', + backgroundColor: '#FFFFFF', + borderRadius: '12px', + padding: '2rem', + // borderColor: '#FFFFFF', +}; From 729769c10cc7f63fa3f46e333c5d0f2a82f2b8fd Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Thu, 5 Sep 2024 02:35:52 +0530 Subject: [PATCH 14/52] edit functionality finished --- src/components/DataAnalysis/OverwriteBox.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 77ce6738..27a1ac00 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -39,6 +39,8 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol } catch (err:any) { console.log(err); errorToast(err.message, [], globalContext); + }finally{ + handleClose(); } } const ModalData: any = { @@ -92,7 +94,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: () => { - console.log('Save as new clicked'); + handleSaveSession(false, null) }, }, { From 0638afa9a26d32b7f5416c5911c0cd3b6f0cc65c Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Thu, 5 Sep 2024 03:06:00 +0530 Subject: [PATCH 15/52] new button resets the form --- src/components/DataAnalysis/OverwriteBox.tsx | 34 ++++++- src/components/DataAnalysis/TopBar.tsx | 3 +- src/pages/analysis/data-analysis.tsx | 102 +++++++++++-------- 3 files changed, 92 insertions(+), 47 deletions(-) diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 27a1ac00..0a560ecf 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -21,6 +21,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol const {data:session} = useSession(); const globalContext = useContext(GlobalContext); const [sessionName, setSessionName] = useState(session_name); + const [openModalName, setOpenModalName] = useState(modalName) const handleClose = () => (setIsBoxOpen(false)); const handleSaveSession =async(overwrite:boolean, old_session_id:string | null)=>{ @@ -82,7 +83,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: () => { - handleSaveSession(true, oldSessionId) + setOpenModalName("CONFIRM_SAVEAS") }, }, { @@ -108,6 +109,31 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol onClick: handleClose, // Use existing handleClose function for the Cancel button },] }, + CONFIRM_SAVEAS:{ + mainheading: "Confirm save as", + subHeading: "Please rename the configuration before saving it in the warehouse", + buttons: [{ + label: 'Save', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(true, oldSessionId) + }, + }, { + label: 'Cancel', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, + },] + }, UNSAVED_CHANGES: { mainheading: "", subHeading: "", @@ -124,7 +150,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol - {ModalData[modalName].mainheading} + {ModalData[openModalName].mainheading} - {ModalData[modalName].subHeading} + {ModalData[openModalName].subHeading} {/* Input Field */} @@ -163,7 +189,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol {/* Dialog Actions */} - {ModalData[modalName].buttons.map((button: any, index: number) => ( + {ModalData[openModalName].buttons.map((button: any, index: number) => ( - -
-
- - -} \ No newline at end of file diff --git a/src/components/DataAnalysis/Feedback.tsx b/src/components/DataAnalysis/Feedback.tsx deleted file mode 100644 index 3eb6390f..00000000 --- a/src/components/DataAnalysis/Feedback.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Box, Button, TextField, Typography } from '@mui/material'; -import CloseIcon from '@/assets/icons/close_small.svg'; -import Image from 'next/image'; -export const FeedBackForm = () => { - return ( - <> - {/* main box */} - - {/* headings */} - info icon - - - - Provide additional feedback - - - Tell us why this response was unsatisfactory{' '} - - - - {/* Input */} - - - - {/* final box */} - - - - - - - ); -}; diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index 0a599432..8a6f5c06 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -1,132 +1,193 @@ -import { Box, Button, Typography } from '@mui/material'; +import { Box, Button, IconButton, Typography } from '@mui/material'; import Image from 'next/image'; import InfoIcon from '@/assets/icons/info.svg'; import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; import CopyIcon from '@/assets/icons/content_copy.svg'; import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; -import { memo, useState } from 'react'; +import { memo, useContext, useState } from 'react'; import { OverWriteDialog } from './OverwriteBox'; +import { successToast } from '../ToastMessage/ToastHelper'; +import { GlobalContext } from '@/contexts/ContextProvider'; -export const LLMSummary = memo(({ llmSummary, newSessionId, prompt, oldSessionMetaInfo }: { llmSummary: string, newSessionId: string, prompt: string, oldSessionMetaInfo: any }) => { - const [isBoxOpen, setIsBoxOpen] = useState(false); - const sessionName = `${prompt}_${Date.now()}`; - const modalName = oldSessionMetaInfo.oldSessionId ? "OVERWRITE" : "SAVE" - console.log("hello") - return ( - <> - - {/* inside the bottom box we will keep everything */} - - - LLM Summary - info icon - - {/* THIS IS THE SUMMARY UI PORTION */} - - logout icon - {llmSummary} +export const LLMSummary = memo( + ({ + llmSummary, + newSessionId, + prompt, + oldSessionMetaInfo, + }: { + llmSummary: string; + newSessionId: string; + prompt: string; + oldSessionMetaInfo: any; + }) => { + const [isBoxOpen, setIsBoxOpen] = useState(false); + const [modalName, setModalName] = useState('SAVE'); + const globalContext = useContext(GlobalContext); + const handleCopyClick = () => { + navigator.clipboard + .writeText(llmSummary) + .then(() => { + successToast('Summary copied to clipboard', [], globalContext); + }) + .catch((err) => { + console.error('Failed to copy text: ', err); + }); + }; + console.log(modalName, 'modalname'); + return ( + <> + + {/* inside the bottom box we will keep everything */} + + LLM Summary logout icon + + {/* THIS IS THE SUMMARY UI PORTION */} + logout icon - logout icon - - - - - + {/* Thumbs Up Icon Button */} + + thumbs up icon + + + {/* Thumbs Down Icon Button with onClick */} + { + setModalName('FEEDBACK_FORM'); + setIsBoxOpen(true); + }} + disabled={!llmSummary} + > + thumbs down icon + + + + + + + + {isBoxOpen && ( + + )} - {isBoxOpen && ( - - )} - - - ); -}); + + ); + } +); const customCss = { display: 'flex', diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 0a560ecf..6a061109 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { Box, Button, @@ -17,62 +17,91 @@ import { useSession } from 'next-auth/react'; import { errorToast, successToast } from '../ToastMessage/ToastHelper'; import { GlobalContext } from '@/contexts/ContextProvider'; -export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,oldSessionId, newSessionId }: { open: boolean, session_name: string, modalName: string, oldSessionId: string, newSessionId:string,setIsBoxOpen: (a: boolean) => void }) => { - const {data:session} = useSession(); +export const OverWriteDialog = ({ + open, + setIsBoxOpen, + modalName, + oldSessionId, + newSessionId, +}: { + open: boolean; + modalName: string; + oldSessionId: string; + newSessionId: string; + setIsBoxOpen: (a: boolean) => void; +}) => { + const { data: session } = useSession(); const globalContext = useContext(GlobalContext); - const [sessionName, setSessionName] = useState(session_name); - const [openModalName, setOpenModalName] = useState(modalName) - const handleClose = () => (setIsBoxOpen(false)); + const [textBoxData, setTextBoxData] = useState(''); + const [openModalName, setOpenModalName] = useState(modalName); + const [isSessionSaved, setIsSessionSaved] = useState(false); + const handleClose = () => setIsBoxOpen(false); - const handleSaveSession =async(overwrite:boolean, old_session_id:string | null)=>{ +console.log(modalName, "modalname"); + const handleSaveSession = async ( + overwrite: boolean, + old_session_id: string | null + ) => { try { - const response = await httpPost(session, `warehouse/ask/${newSessionId}/save`, { - "session_name": sessionName, - overwrite, - old_session_id - }); - console.log(response, "response"); + const response = await httpPost( + session, + `warehouse/ask/${newSessionId}/save`, + { + session_name: textBoxData, + overwrite, + old_session_id, + } + ); + console.log(response, 'response'); //write error condition - if(response.success){ - successToast(`${sessionName} saved successfully`, [], globalContext); + if (response.success) { + successToast(`${textBoxData} saved successfully`, [], globalContext); + setIsSessionSaved(true); } - - } catch (err:any) { + } catch (err: any) { console.log(err); errorToast(err.message, [], globalContext); - }finally{ + } finally { handleClose(); } - } + }; + + + const ModalData: any = { SAVE: { - mainheading: "Save as", - subHeading: "Please name the configuration before saving it in the warehouse", - buttons: [{ - label: 'Save', - variant: 'contained', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', - }, - onClick: () => { - handleSaveSession(false, null) + mainheading: 'Save as', + subHeading: + 'Please name the configuration before saving it in the warehouse', + buttons: [ + { + label: 'Save', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(false, null); + }, }, - }, { - label: 'Cancel', - variant: 'outlined', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', + { + label: 'Cancel', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, }, - onClick: handleClose, - },] + ], }, OVERWRITE: { - mainheading: "Overwrite existing session", - subHeading: "The session with this name already exists. Do you want to overwrite?", + mainheading: 'Overwrite existing session', + subHeading: + 'The session with this name already exists. Do you want to overwrite?', buttons: [ { label: 'Overwrite', @@ -83,7 +112,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: () => { - setOpenModalName("CONFIRM_SAVEAS") + setOpenModalName('CONFIRM_SAVEAS'); }, }, { @@ -95,7 +124,7 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: () => { - handleSaveSession(false, null) + handleSaveSession(false, null); }, }, { @@ -107,13 +136,63 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: handleClose, // Use existing handleClose function for the Cancel button - },] + }, + ], }, - CONFIRM_SAVEAS:{ - mainheading: "Confirm save as", - subHeading: "Please rename the configuration before saving it in the warehouse", - buttons: [{ - label: 'Save', + CONFIRM_SAVEAS: { + mainheading: 'Confirm save as', + subHeading: + 'Please rename the configuration before saving it in the warehouse', + buttons: [ + { + label: 'Save', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(true, oldSessionId); //overwriting, opens when clicked overwrite. + }, + }, + { + label: 'Cancel', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, + }, + ], + }, + FEEDBACK_FORM: { + mainheading: 'Provide additional feedback', + subHeading: 'Tell us why this response was unsatisfactory', + rowsNum: 5, + label: "Feedback", + buttons: [ + { + label: 'Submit', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + + }, + }, + ], + }, + UNSAVED_CHANGES: { + mainheading: 'Unsaved changes', + subHeading: 'You are about to leave this page without saving the changes.\nAll the changes that were made will be lost. Do you wish to continue?', + buttons: [ { + label: 'Save changes', variant: 'contained', sx: { width: '6.75rem', @@ -121,10 +200,11 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: () => { - handleSaveSession(true, oldSessionId) + handleSaveSession(false, oldSessionId); }, - }, { - label: 'Cancel', + }, + { + label: 'Leave anyway', variant: 'outlined', sx: { width: '6.75rem', @@ -132,14 +212,9 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol borderRadius: '5px', }, onClick: handleClose, - },] + },], }, - UNSAVED_CHANGES: { - mainheading: "", - subHeading: "", - buttons: [{}, {}] - } - } + }; return ( <> {/* Dialog Box */} @@ -179,30 +254,41 @@ export const OverWriteDialog = ({ open, setIsBoxOpen, session_name, modalName,ol { setSessionName(e.target.value) }} + value={textBoxData} + onChange={(e) => { + setTextBoxData(e.target.value); + }} /> {/* Dialog Actions */} - - {ModalData[openModalName].buttons.map((button: any, index: number) => ( - - ))} + + {ModalData[openModalName].buttons.map( + (button: any, index: number) => ( + + ) + )}
); }; - - diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx index e1bc426b..92c9735f 100644 --- a/src/components/DataAnalysis/SavedSession.tsx +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -8,284 +8,372 @@ import { Paper, TableHead, TableRow, + Tooltip, Button, TablePagination, + CircularProgress, } from '@mui/material'; import Image from 'next/image'; import InfoIcon from '@/assets/icons/info.svg'; -import CloseIcon from "@/assets/icons/close_small.svg"; -import ArrowIcon from "@/assets/icons/arrow_back_ios.svg" -import { useEffect, useState } from 'react'; +import CloseIcon from '@/assets/icons/close_small.svg'; +import ArrowIcon from '@/assets/icons/arrow_back_ios.svg'; +import { memo, useContext, useEffect, useState } from 'react'; import { httpGet } from '@/helpers/http'; import { useSession } from 'next-auth/react'; +import moment from 'moment'; +import { errorToast } from '../ToastMessage/ToastHelper'; +import { GlobalContext } from '@/contexts/ContextProvider'; +export const SavedSession = memo( + ({ + open, + onClose, + handleEditSession, + }: { + open: boolean; + onClose: any; + handleEditSession: any; + }) => { + const { data: session } = useSession(); + const globalContext = useContext(GlobalContext); + const [pageSize, setPageSize] = useState(5); // Default rows per page + const [totalCount, setTotalCount] = useState(0); // Total count of rows + const [currentPageIndex, setCurrentPageIndex] = useState(0); // Page index starts from 0 + const [savedSessions, setSavedSession] = useState([]); + const [loading, setLoading] = useState(false); + const [activeRow, setActiveRow] = useState(null); // State to track the clicked row + const getSavedSessions = async (pageIndex: number, rowsPerPage: number) => { + setLoading(true); + try { + const offset = pageIndex * rowsPerPage; + const response = await httpGet( + session, + `warehouse/ask/sessions?limit=${rowsPerPage}&offset=${offset}` + ); + console.log(response, 'response'); + if (!response.rows) { + errorToast('Something went wrong', [], globalContext); + return; + } + setSavedSession(response.rows); + setTotalCount(response.total_rows); + } catch (error: any) { + console.log(error); + errorToast(error.message, [], globalContext); + } finally { + setLoading(false); + } + }; -export const SavedSession = ({ open, onClose, handleEditSession }: { open: boolean, onClose: any, handleEditSession:any }) => { - const {data: session} = useSession(); - const [pageSize, setPageSize] = useState(0); - const [totalCount, setTotalCount] = useState(0); // Total count of rows - const [pageCount, setPageCount] = useState(0); // Total number of pages - const [currentPageIndex, setCurrentPageIndex] = useState(1); // Page index - const [savedSessions, setSavedSession] = useState([]); + useEffect(() => { + if (session) { + getSavedSessions(currentPageIndex, pageSize); + } + }, [session, currentPageIndex, pageSize]); - useEffect(()=>{ - const getSavedSessions = async ()=>{ - const response = await httpGet(session, `warehouse/ask/sessions?limit=${10}&offset=${pageSize}`); - console.log(response, "response"); - setSavedSession(response) - } - getSavedSessions(); - },[session]) + const handlePagination = (newPageIndex: number, newPageSize: number) => { + setCurrentPageIndex(newPageIndex); + getSavedSessions(newPageIndex, newPageSize); + }; + + const formatDate = (date: string) => { + return moment(date).format('MMM DD, YYYY'); + }; - return ( - <> - { + if (text.length > maxLength) { + return `${text.substring(0, maxLength)}...`; + } + return text; + }; - }, - }} - > - {/* MAIN BOX */} - + - Saved Sessions + + Saved Sessions + info icon + info icon - close icon - - - - - - - - - - Created On - - - Updated On - - - Name - - - Created By - - - - - {savedSessions.map((row:any, idx) => ( - +
+ + + - {idx} + Created On - {row.createdOn} + Updated On - {row.updatedOn} + Name - {row.session_name} + Status - {row.createdBy} - - - - ))} - - - -
-
+ + {idx + 1 + currentPageIndex * pageSize} + + + {formatDate(row.created_at)} + + + {formatDate(row.updated_at)} + + + + {trimText(row.session_name, 20)} + + + + {row.session_status} + + + {row.created_by.email} + + + + )) + )} + + + setCurrentPageIndex(newPage + 1)} - onRowsPerPageChange={(e: any) => { - setPageSize(e.target.value); - setCurrentPageIndex(1); - }} - /> -
-
- - ); -}; + rowsPerPageOptions={[5, 10]} + component="div" + count={totalCount} + rowsPerPage={pageSize} + page={currentPageIndex} + onPageChange={(e, newPage) => { + handlePagination(newPage, pageSize); + }} + onRowsPerPageChange={(e: any) => { + const newPageSize = parseInt(e.target.value, 10); + setPageSize(newPageSize); + setCurrentPageIndex(0); // Reset to first page on rows per page change + handlePagination(0, newPageSize); + }} + /> + + + + ); + } +); diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index e49ac7ec..bf3fcb06 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -1,30 +1,39 @@ import { Box, Button, + CircularProgress, TextField, Typography, } from '@mui/material'; import Image from 'next/image'; import CloseIcon from '@/assets/icons/close_small.svg'; -import { useContext, useEffect, useMemo, useState } from 'react'; +import { memo, useContext, useEffect, useState } from 'react'; import { GlobalContext } from '@/contexts/ContextProvider'; import { errorToast } from '../ToastMessage/ToastHelper'; import { httpGet } from '@/helpers/http'; import { useSession } from 'next-auth/react'; - - -export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSessionMetaInfo }: { getLLMSummary: any, prompt: string, loading: boolean, oldSessionMetaInfo: any, newSessionId: string }) => { +export const SqlWrite = memo(({ + getLLMSummary, + prompt, + newSessionId, + oldSessionMetaInfo, +}: { + getLLMSummary: any; + prompt: string; + oldSessionMetaInfo: any; + newSessionId: string; +}) => { const { data: session } = useSession(); const [defaultPromptsLists, setDefaultPromptLists] = useState([]); const [customPromptToggle, setCustomPromptToggle] = useState(false); - const [customPrompt, setCustomPrompt] = useState(""); - const [defaultPrompt, setDefaultPrompt] = useState(""); - const [sqlText, setSqlText] = useState(""); + const [customPrompt, setCustomPrompt] = useState(''); + const [defaultPrompt, setDefaultPrompt] = useState(''); + const [sqlText, setSqlText] = useState(''); const globalContext = useContext(GlobalContext); - + const [tempLoading, setTempLoading] = useState(false); const handlePromptSelection = (promptText: string) => { if (customPromptToggle) { @@ -53,38 +62,49 @@ export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSess }); }; - useEffect(() => { - console.log("hellooooooooooooooooooooooooooo") try { + setTempLoading(true); const getDefaultPrompts = async () => { const response = await httpGet(session, `data/user_prompts/`); - console.log(response, "response"); - if (response.length) { - const isDefaultPrompt = response.some((item: any) => { - return item?.prompt === prompt; - }); - - console.log(isDefaultPrompt, "isdeafult") - setCustomPromptToggle(isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true); - setCustomPrompt(isDefaultPrompt ? "" : prompt); - setDefaultPrompt(isDefaultPrompt ? prompt : ""); - setSqlText(oldSessionMetaInfo?.sqlText || ""); + if (!response.length) { + errorToast('No Custom Prompts found', [], globalContext); + return; } + setDefaultPromptLists(response); + }; - setDefaultPromptLists(response) - } if (session) { getDefaultPrompts(); } - } catch (error) { - console.log(error) + } catch (error: any) { + console.log(error); + errorToast(error.message, [], globalContext); + } finally { + setTempLoading(false); } - }, [session, oldSessionMetaInfo.sqlText]) + }, [session]); + useEffect(() => { + const isDefaultPrompt = defaultPromptsLists.some((item: any) => { + return item?.prompt === prompt; + }); + setCustomPromptToggle( + isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true + ); + setCustomPrompt(isDefaultPrompt ? '' : prompt); + setDefaultPrompt(isDefaultPrompt ? prompt : ''); + setSqlText(oldSessionMetaInfo?.sqlText || ''); + }, [defaultPromptsLists, oldSessionMetaInfo]); + + + if (tempLoading) return ; return ( <> - + {/* second box */}
@@ -177,7 +197,9 @@ export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSess sx={{ flex: '1 1 auto', backgroundColor: - defaultPrompt === defaultPrompts.prompt ? '#05443e' : '#00897B', + defaultPrompt === defaultPrompts.prompt + ? '#05443e' + : '#00897B', }} onClick={() => { handlePromptSelection(defaultPrompts.prompt); @@ -187,7 +209,7 @@ export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSess {defaultPrompts.label} - ) + ); })}
@@ -252,7 +274,7 @@ export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSess variant="contained" sx={{ width: '6.75rem', - marginTop: '6rem', + marginTop: '8rem', padding: '8px 0', borderRadius: '5px', }} @@ -260,9 +282,6 @@ export const SqlWrite = ({ getLLMSummary, prompt, loading, newSessionId, oldSess Submit
- ); -}; - - +}); diff --git a/src/components/DataAnalysis/UnsavedChanges.tsx b/src/components/DataAnalysis/UnsavedChanges.tsx deleted file mode 100644 index 1986e87f..00000000 --- a/src/components/DataAnalysis/UnsavedChanges.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Box, Button, TextField, Typography } from '@mui/material'; -import CloseIcon from '@/assets/icons/close_small.svg'; -import Image from 'next/image'; -export const UnsavedChanges = ()=>{ - return <> - - {/* main box */} - - {/* headings */} - info icon - - - - Unsaved changes - - - You are about to leave this page without saving the changes. - All the changes that were made will be lost. Do you wish to continue? - - - - {/* Input */} - - - - {/* final box */} - - - - - - - -} \ No newline at end of file diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index d8742f3c..2ff1566b 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -69,6 +69,12 @@ export default function DataAnalysis() { const pollForTaskRun = async (taskId: string) => { try { const response: any = await httpGet(session, 'tasks/stp/' + taskId); + console.log(response, "pollresp") + const response1 = await httpGet( + session, + `warehouse/ask/sessions?limit=${100}&offset=${0}` + ); + console.log(response1, "reps111") const lastMessage: any = response['progress'][response['progress'].length - 1]; if (!['completed', 'failed'].includes(lastMessage.status)) { @@ -129,6 +135,7 @@ export default function DataAnalysis() { } }; + return ( <> From b965cc92099c1b7079ae7581975df4508e09215e Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Thu, 5 Sep 2024 22:23:45 +0530 Subject: [PATCH 17/52] commits --- src/components/DataAnalysis/LLMSummary.tsx | 3 + src/components/DataAnalysis/OverwriteBox.tsx | 3 + src/components/DataAnalysis/SqlWrite.tsx | 471 ++++++++++--------- src/pages/analysis/data-analysis.tsx | 1 + 4 files changed, 244 insertions(+), 234 deletions(-) diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index 8a6f5c06..ad7514da 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -16,11 +16,13 @@ export const LLMSummary = memo( newSessionId, prompt, oldSessionMetaInfo, + handleNewSession }: { llmSummary: string; newSessionId: string; prompt: string; oldSessionMetaInfo: any; + handleNewSession: any }) => { const [isBoxOpen, setIsBoxOpen] = useState(false); const [modalName, setModalName] = useState('SAVE'); @@ -181,6 +183,7 @@ export const LLMSummary = memo( modalName={modalName} oldSessionId={oldSessionMetaInfo.oldSessionId} newSessionId={newSessionId} + handleNewSession={handleNewSession} /> )}
diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 6a061109..5266ef3e 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -23,11 +23,13 @@ export const OverWriteDialog = ({ modalName, oldSessionId, newSessionId, + handleNewSession }: { open: boolean; modalName: string; oldSessionId: string; newSessionId: string; + handleNewSession:any setIsBoxOpen: (a: boolean) => void; }) => { const { data: session } = useSession(); @@ -57,6 +59,7 @@ console.log(modalName, "modalname"); if (response.success) { successToast(`${textBoxData} saved successfully`, [], globalContext); setIsSessionSaved(true); + handleNewSession(); } } catch (err: any) { console.log(err); diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index bf3fcb06..f1c98736 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -15,273 +15,276 @@ import { errorToast } from '../ToastMessage/ToastHelper'; import { httpGet } from '@/helpers/http'; import { useSession } from 'next-auth/react'; -export const SqlWrite = memo(({ - getLLMSummary, - prompt, - newSessionId, - oldSessionMetaInfo, -}: { - getLLMSummary: any; - prompt: string; - oldSessionMetaInfo: any; - newSessionId: string; -}) => { - const { data: session } = useSession(); - const [defaultPromptsLists, setDefaultPromptLists] = useState([]); - const [customPromptToggle, setCustomPromptToggle] = useState(false); - const [customPrompt, setCustomPrompt] = useState(''); - const [defaultPrompt, setDefaultPrompt] = useState(''); - const [sqlText, setSqlText] = useState(''); - const globalContext = useContext(GlobalContext); - const [tempLoading, setTempLoading] = useState(false); +export const SqlWrite = memo( + ({ + getLLMSummary, + prompt, + newSessionId, + oldSessionMetaInfo, + }: { + getLLMSummary: any; + prompt: string; + oldSessionMetaInfo: any; + newSessionId: string; + }) => { + const { data: session } = useSession(); + const [defaultPromptsLists, setDefaultPromptLists] = useState([]); + const [customPromptToggle, setCustomPromptToggle] = useState(false); + const [customPrompt, setCustomPrompt] = useState(''); + const [defaultPrompt, setDefaultPrompt] = useState(''); + const [sqlText, setSqlText] = useState(''); + const globalContext = useContext(GlobalContext); + const [tempLoading, setTempLoading] = useState(false); - const handlePromptSelection = (promptText: string) => { - if (customPromptToggle) { - setCustomPrompt(''); - setCustomPromptToggle(false); - } - setDefaultPrompt(promptText); - }; + const handlePromptSelection = (promptText: string) => { + if (customPromptToggle) { + setCustomPrompt(''); + setCustomPromptToggle(false); + } + setDefaultPrompt(promptText); + }; - const handleSubmit = async () => { - if (!sqlText) { - errorToast('Please enter a SELECT sql query', [], globalContext); - return; - } - if (!customPrompt && !defaultPrompt) { - errorToast( - 'Either select a default prompt or write a custom prompt', - [], - globalContext - ); - return; - } - getLLMSummary({ - sqlText, - user_prompt: customPrompt || defaultPrompt, - }); - }; + const handleSubmit = async () => { + if (!sqlText) { + errorToast('Please enter a SELECT sql query', [], globalContext); + return; + } + if (!customPrompt && !defaultPrompt) { + errorToast( + 'Either select a default prompt or write a custom prompt', + [], + globalContext + ); + return; + } + getLLMSummary({ + sqlText, + user_prompt: customPrompt || defaultPrompt, + }); + }; - useEffect(() => { - try { - setTempLoading(true); - const getDefaultPrompts = async () => { - const response = await httpGet(session, `data/user_prompts/`); - if (!response.length) { - errorToast('No Custom Prompts found', [], globalContext); - return; - } - setDefaultPromptLists(response); - }; + useEffect(() => { + try { + setTempLoading(true); + const getDefaultPrompts = async () => { + const response = await httpGet(session, `data/user_prompts/`); + if (!response.length) { + errorToast('No Custom Prompts found', [], globalContext); + return; + } + setDefaultPromptLists(response); + }; - if (session) { - getDefaultPrompts(); + if (session) { + getDefaultPrompts(); + } + } catch (error: any) { + console.log(error); + errorToast(error.message, [], globalContext); + } finally { + setTempLoading(false); } - } catch (error: any) { - console.log(error); - errorToast(error.message, [], globalContext); - } finally { - setTempLoading(false); - } - }, [session]); - - useEffect(() => { - const isDefaultPrompt = defaultPromptsLists.some((item: any) => { - return item?.prompt === prompt; - }); - setCustomPromptToggle( - isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true - ); - setCustomPrompt(isDefaultPrompt ? '' : prompt); - setDefaultPrompt(isDefaultPrompt ? prompt : ''); - setSqlText(oldSessionMetaInfo?.sqlText || ''); - }, [defaultPromptsLists, oldSessionMetaInfo]); + }, [session]); + useEffect(() => { + const isDefaultPrompt = defaultPromptsLists.some((item: any) => { + return item?.prompt === prompt; + }); + setCustomPromptToggle( + isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true + ); + setCustomPrompt(isDefaultPrompt ? '' : prompt); + setDefaultPrompt(isDefaultPrompt ? prompt : ''); + setSqlText(oldSessionMetaInfo?.sqlText || ''); + }, [defaultPromptsLists, oldSessionMetaInfo]); - if (tempLoading) return ; - return ( - <> - - {/* second box */} - -
-
- {/* Third box with sql editor */} + if (tempLoading) return ; + return ( + <> + + {/* second box */} + +
+
+ {/* Third box with sql editor */} - - - SQL Filter* - + + + SQL Filter* + - {/* This contains the sql filter */} - { - setSqlText(e.target.value); - }} - /> - + {/* This contains the sql filter */} + { + setSqlText(e.target.value); + }} + /> + - {/* foruth box with some buttons */} - + {/* foruth box with some buttons */} - - Select a prompt* - - - (Choose any one from the given prompts) - + + Select a prompt* + + + (Choose any one from the given prompts) + + - - - {defaultPromptsLists.map((defaultPrompts: any) => { - return ( + + {defaultPromptsLists.map((defaultPrompts: any) => { + return ( + + ); + })} + + + + OR + + + + {customPromptToggle ? ( + + + Custom Prompt + { + setCustomPromptToggle(false); + setCustomPrompt(''); + }} + alt="close icon" + /> + + { + setCustomPrompt(e.target.value); + }} + /> + + ) : ( - ); - })} + )} + - - { + handleSubmit(); + }} + disabled={newSessionId ? true : false} + variant="contained" + sx={{ + width: '6.75rem', + marginTop: '2.5rem', + padding: '8px 0', + borderRadius: '5px', + }} > - OR - - - {customPromptToggle ? ( - - - Custom Prompt - { - setCustomPromptToggle(false); - setCustomPrompt(''); - }} - alt="close icon" - /> - - { - setCustomPrompt(e.target.value); - }} - /> - - ) : ( - - )} + Submit +
- -
- - ); -}); + + ); + } +); diff --git a/src/pages/analysis/data-analysis.tsx b/src/pages/analysis/data-analysis.tsx index 2ff1566b..7a06606f 100644 --- a/src/pages/analysis/data-analysis.tsx +++ b/src/pages/analysis/data-analysis.tsx @@ -171,6 +171,7 @@ export default function DataAnalysis() { newSessionId={newSessionId} oldSessionMetaInfo={oldSessionMetaInfo} prompt={prompt} + handleNewSession={handleNewSession} /> {/* Loader full screen */} From e688d0bade3ec63fbb09332f197d423529703fe2 Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Thu, 5 Sep 2024 23:05:42 +0530 Subject: [PATCH 18/52] code adjustments and removed the closeicon svg --- src/assets/icons/close_small.svg | 8 --- src/components/DataAnalysis/OverwriteBox.tsx | 66 ++++++++++---------- src/components/DataAnalysis/SavedSession.tsx | 59 ++++++++--------- src/components/DataAnalysis/SqlWrite.tsx | 10 ++- src/pages/analysis/data-analysis.tsx | 11 +--- 5 files changed, 66 insertions(+), 88 deletions(-) delete mode 100644 src/assets/icons/close_small.svg diff --git a/src/assets/icons/close_small.svg b/src/assets/icons/close_small.svg deleted file mode 100644 index 45e22332..00000000 --- a/src/assets/icons/close_small.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 5266ef3e..10c4bf33 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -10,8 +10,7 @@ import { DialogTitle, IconButton, } from '@mui/material'; -import Image from 'next/image'; -import CloseIcon from '@/assets/icons/close_small.svg'; +import CloseIcon from '@mui/icons-material/Close'; import { httpPost } from '@/helpers/http'; import { useSession } from 'next-auth/react'; import { errorToast, successToast } from '../ToastMessage/ToastHelper'; @@ -23,13 +22,13 @@ export const OverWriteDialog = ({ modalName, oldSessionId, newSessionId, - handleNewSession + handleNewSession, }: { open: boolean; modalName: string; oldSessionId: string; newSessionId: string; - handleNewSession:any + handleNewSession: any; setIsBoxOpen: (a: boolean) => void; }) => { const { data: session } = useSession(); @@ -39,7 +38,7 @@ export const OverWriteDialog = ({ const [isSessionSaved, setIsSessionSaved] = useState(false); const handleClose = () => setIsBoxOpen(false); -console.log(modalName, "modalname"); + console.log(modalName, 'modalname'); const handleSaveSession = async ( overwrite: boolean, old_session_id: string | null @@ -69,8 +68,6 @@ console.log(modalName, "modalname"); } }; - - const ModalData: any = { SAVE: { mainheading: 'Save as', @@ -175,7 +172,7 @@ console.log(modalName, "modalname"); mainheading: 'Provide additional feedback', subHeading: 'Tell us why this response was unsatisfactory', rowsNum: 5, - label: "Feedback", + label: 'Feedback', buttons: [ { label: 'Submit', @@ -185,37 +182,38 @@ console.log(modalName, "modalname"); padding: '8px 0', borderRadius: '5px', }, - onClick: () => { - - }, + onClick: () => {}, }, ], }, UNSAVED_CHANGES: { mainheading: 'Unsaved changes', - subHeading: 'You are about to leave this page without saving the changes.\nAll the changes that were made will be lost. Do you wish to continue?', - buttons: [ { - label: 'Save changes', - variant: 'contained', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', - }, - onClick: () => { - handleSaveSession(false, oldSessionId); + subHeading: + 'You are about to leave this page without saving the changes.\nAll the changes that were made will be lost. Do you wish to continue?', + buttons: [ + { + label: 'Save changes', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + handleSaveSession(false, oldSessionId); + }, }, - }, - { - label: 'Leave anyway', - variant: 'outlined', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', + { + label: 'Leave anyway', + variant: 'outlined', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: handleClose, }, - onClick: handleClose, - },], + ], }, }; return ( @@ -235,7 +233,7 @@ console.log(modalName, "modalname"); onClick={handleClose} aria-label="close" > - Close +
@@ -259,7 +257,7 @@ console.log(modalName, "modalname"); fullWidth multiline rows={ModalData[openModalName]?.rowsNum || 1} - label={ModalData[openModalName]?.label || "Session Name"} + label={ModalData[openModalName]?.label || 'Session Name'} variant="outlined" value={textBoxData} onChange={(e) => { diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx index 92c9735f..7d079630 100644 --- a/src/components/DataAnalysis/SavedSession.tsx +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -16,7 +16,7 @@ import { import Image from 'next/image'; import InfoIcon from '@/assets/icons/info.svg'; -import CloseIcon from '@/assets/icons/close_small.svg'; +import CloseIcon from '@mui/icons-material/Close'; import ArrowIcon from '@/assets/icons/arrow_back_ios.svg'; import { memo, useContext, useEffect, useState } from 'react'; import { httpGet } from '@/helpers/http'; @@ -140,20 +140,15 @@ export const SavedSession = memo( alt="info icon" /> - close icon + - + {loading ? ( ) : ( @@ -243,18 +238,18 @@ export const SavedSession = memo( backgroundColor: activeRow === row.session_id ? '#E0F7FA' - : 'inherit', // Active row color on click + : 'inherit', '&:hover': { - backgroundColor: '#F5FAFA', // Hover background color + backgroundColor: '#F5FAFA', }, '&:hover .hover-button': { visibility: 'visible', opacity: 1, }, - border: 'none', // Ensure no border is applied - boxShadow: 'none', // Remove any default shadows + border: 'none', + boxShadow: 'none', }} - onClick={() => setActiveRow(row.session_id)} // Set the active row on click + onClick={() => setActiveRow(row.session_id)} >
- { - handlePagination(newPage, pageSize); - }} - onRowsPerPageChange={(e: any) => { - const newPageSize = parseInt(e.target.value, 10); - setPageSize(newPageSize); - setCurrentPageIndex(0); // Reset to first page on rows per page change - handlePagination(0, newPageSize); - }} - /> + { + handlePagination(newPage, pageSize); + }} + onRowsPerPageChange={(e: any) => { + const newPageSize = parseInt(e.target.value, 10); + setPageSize(newPageSize); + setCurrentPageIndex(0); + handlePagination(0, newPageSize); + }} + /> diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index f1c98736..6e333949 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -5,9 +5,9 @@ import { TextField, Typography, } from '@mui/material'; -import Image from 'next/image'; -import CloseIcon from '@/assets/icons/close_small.svg'; +import CloseIcon from '@mui/icons-material/Close'; + import { memo, useContext, useEffect, useState } from 'react'; import { GlobalContext } from '@/contexts/ContextProvider'; @@ -230,14 +230,12 @@ export const SqlWrite = memo( }} > Custom Prompt - { setCustomPromptToggle(false); setCustomPrompt(''); }} - alt="close icon" + sx={{ cursor: 'pointer' }} /> Date: Fri, 6 Sep 2024 02:32:03 +0530 Subject: [PATCH 19/52] changed the log and made function comman, and some toher changes --- src/assets/icons/aianalysis.tsx | 62 +++++++ src/components/DataAnalysis/LLMSummary.tsx | 27 +-- src/components/DataAnalysis/SqlWrite.tsx | 196 ++++++++++++--------- src/components/Layouts/Auth.tsx | 3 +- src/config/menu.tsx | 3 +- src/pages/analysis/data-analysis.tsx | 4 +- src/utils/common.tsx | 16 +- 7 files changed, 204 insertions(+), 107 deletions(-) create mode 100644 src/assets/icons/aianalysis.tsx diff --git a/src/assets/icons/aianalysis.tsx b/src/assets/icons/aianalysis.tsx new file mode 100644 index 00000000..d5121eac --- /dev/null +++ b/src/assets/icons/aianalysis.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; +const AiAnalysis = (props: any) => ( + + + + + + + + + +); +export default AiAnalysis; diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index ad7514da..89d95594 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -7,8 +7,9 @@ import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; import { memo, useContext, useState } from 'react'; import { OverWriteDialog } from './OverwriteBox'; -import { successToast } from '../ToastMessage/ToastHelper'; +import { errorToast, successToast } from '../ToastMessage/ToastHelper'; import { GlobalContext } from '@/contexts/ContextProvider'; +import { copyToClipboard } from '@/utils/common'; export const LLMSummary = memo( ({ @@ -16,26 +17,28 @@ export const LLMSummary = memo( newSessionId, prompt, oldSessionMetaInfo, - handleNewSession + handleNewSession, }: { llmSummary: string; newSessionId: string; prompt: string; oldSessionMetaInfo: any; - handleNewSession: any + handleNewSession: any; }) => { const [isBoxOpen, setIsBoxOpen] = useState(false); const [modalName, setModalName] = useState('SAVE'); const globalContext = useContext(GlobalContext); - const handleCopyClick = () => { - navigator.clipboard - .writeText(llmSummary) - .then(() => { - successToast('Summary copied to clipboard', [], globalContext); - }) - .catch((err) => { - console.error('Failed to copy text: ', err); - }); + const handleCopyClick = async () => { + const copyRes: boolean = await copyToClipboard(llmSummary); + if (copyRes) { + successToast('Successfully copied to clipboard', [], globalContext); + } else { + errorToast( + 'Some problem with copying. Please try again', + [], + globalContext + ); + } }; console.log(modalName, 'modalname'); return ( diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index 6e333949..5f4472c9 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -5,11 +5,9 @@ import { TextField, Typography, } from '@mui/material'; - import CloseIcon from '@mui/icons-material/Close'; - import { memo, useContext, useEffect, useState } from 'react'; - +import { useForm, Controller } from 'react-hook-form'; import { GlobalContext } from '@/contexts/ContextProvider'; import { errorToast } from '../ToastMessage/ToastHelper'; import { httpGet } from '@/helpers/http'; @@ -30,25 +28,35 @@ export const SqlWrite = memo( const { data: session } = useSession(); const [defaultPromptsLists, setDefaultPromptLists] = useState([]); const [customPromptToggle, setCustomPromptToggle] = useState(false); - const [customPrompt, setCustomPrompt] = useState(''); - const [defaultPrompt, setDefaultPrompt] = useState(''); - const [sqlText, setSqlText] = useState(''); const globalContext = useContext(GlobalContext); const [tempLoading, setTempLoading] = useState(false); + const { + control, + setValue, + watch, + handleSubmit, + formState: { errors }, + reset, + } = useForm({ + defaultValues: { + defaultPrompt: '', + customPrompt: '', + sqlText: '', + }, + }); + + const selectedDefaultPrompt = watch('defaultPrompt'); + const customPromptValue = watch('customPrompt'); + const handlePromptSelection = (promptText: string) => { - if (customPromptToggle) { - setCustomPrompt(''); - setCustomPromptToggle(false); - } - setDefaultPrompt(promptText); + setCustomPromptToggle(false); + setValue('defaultPrompt', promptText); + setValue('customPrompt', ''); }; - const handleSubmit = async () => { - if (!sqlText) { - errorToast('Please enter a SELECT sql query', [], globalContext); - return; - } + const onSubmit = (data: any) => { + const { sqlText, customPrompt, defaultPrompt } = data; if (!customPrompt && !defaultPrompt) { errorToast( 'Either select a default prompt or write a custom prompt', @@ -64,25 +72,24 @@ export const SqlWrite = memo( }; useEffect(() => { - try { - setTempLoading(true); - const getDefaultPrompts = async () => { + const getDefaultPrompts = async () => { + try { + setTempLoading(true); const response = await httpGet(session, `data/user_prompts/`); if (!response.length) { errorToast('No Custom Prompts found', [], globalContext); return; } setDefaultPromptLists(response); - }; - - if (session) { - getDefaultPrompts(); + } catch (error: any) { + errorToast(error.message, [], globalContext); + } finally { + setTempLoading(false); } - } catch (error: any) { - console.log(error); - errorToast(error.message, [], globalContext); - } finally { - setTempLoading(false); + }; + + if (session) { + getDefaultPrompts(); } }, [session]); @@ -93,24 +100,27 @@ export const SqlWrite = memo( setCustomPromptToggle( isDefaultPrompt || !oldSessionMetaInfo.sqlText ? false : true ); - setCustomPrompt(isDefaultPrompt ? '' : prompt); - setDefaultPrompt(isDefaultPrompt ? prompt : ''); - setSqlText(oldSessionMetaInfo?.sqlText || ''); + reset({ + defaultPrompt: isDefaultPrompt ? prompt : '', + customPrompt: isDefaultPrompt ? '' : prompt, + sqlText: oldSessionMetaInfo?.sqlText || '', + }); }, [defaultPromptsLists, oldSessionMetaInfo]); if (tempLoading) return ; + return ( <> - {/* second box */} + {/* Second box */}
- {/* Third box with sql editor */} + {/* SQL Editor */} - {/* This contains the sql filter */} - { - setSqlText(e.target.value); - }} + ( + + )} /> - {/* foruth box with some buttons */} + {/* Prompt Selection */} - {defaultPromptsLists.map((defaultPrompts: any) => { - return ( - - ); - })} + {defaultPromptsLists.map((defaultPrompts: any) => ( + + ))} { setCustomPromptToggle(false); - setCustomPrompt(''); + setValue('customPrompt', ''); }} sx={{ cursor: 'pointer' }} />
- { - setCustomPrompt(e.target.value); - }} + + ( + + )} /> ) : ( + + + - - - - + + + New + + + - + -} - + ); +}; From 4ae5b4b8b05e4c9f5cefc9eb5e04472c275c7cdd Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Fri, 6 Sep 2024 23:30:43 +0530 Subject: [PATCH 21/52] used the custom Dailog in overwrite box --- src/components/DataAnalysis/LLMSummary.tsx | 390 ++++++++++--------- src/components/DataAnalysis/OverwriteBox.tsx | 243 +++++------- src/components/DataAnalysis/SavedSession.tsx | 39 +- 3 files changed, 318 insertions(+), 354 deletions(-) diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index cbda6376..ed97b4f3 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -1,206 +1,230 @@ import { Box, Button, IconButton, Typography } from '@mui/material'; import Image from 'next/image'; -import InfoIcon from '@/assets/icons/info.svg'; -import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; +import { useEffect, useState, useContext } from 'react'; +import { OverWriteDialog } from './OverwriteBox'; +import { useRouter } from 'next/router'; +import { GlobalContext } from '@/contexts/ContextProvider'; +import InfoTooltip from '../UI/Tooltip/Tooltip'; import CopyIcon from '@/assets/icons/content_copy.svg'; +import DalgoIcon from '@/assets/icons/dalgoIcon.svg'; import ThumbsupIcon from '@/assets/icons/thumb_up.svg'; import ThumbsDownIcon from '@/assets/icons/thumb_up (1).svg'; -import { memo, useContext, useState } from 'react'; -import { OverWriteDialog } from './OverwriteBox'; -import { errorToast, successToast } from '../ToastMessage/ToastHelper'; -import { GlobalContext } from '@/contexts/ContextProvider'; import { copyToClipboard } from '@/utils/common'; -import InfoTooltip from '../UI/Tooltip/Tooltip'; +import { successToast, errorToast } from '../ToastMessage/ToastHelper'; +import { httpPost } from '@/helpers/http'; +import { useSession } from 'next-auth/react'; -export const LLMSummary = memo( - ({ - llmSummary, - newSessionId, - prompt, - oldSessionMetaInfo, - handleNewSession, - }: { - llmSummary: string; - newSessionId: string; - prompt: string; - oldSessionMetaInfo: any; - handleNewSession: any; - }) => { - const [isBoxOpen, setIsBoxOpen] = useState(false); - const [modalName, setModalName] = useState('SAVE'); - const globalContext = useContext(GlobalContext); - const handleCopyClick = async () => { - const copyRes: boolean = await copyToClipboard(llmSummary); - if (copyRes) { - successToast('Successfully copied to clipboard', [], globalContext); - } else { - errorToast( - 'Some problem with copying. Please try again', - [], - globalContext - ); +export const LLMSummary = ({ + llmSummary, + newSessionId, + prompt, + oldSessionMetaInfo, + handleNewSession, +}: { + llmSummary: string; + newSessionId: string; + prompt: string; + oldSessionMetaInfo: any; + handleNewSession: any; +}) => { + const router = useRouter(); + const {data:session} = useSession(); + const [isBoxOpen, setIsBoxOpen] = useState(false); + const [modalName, setModalName] = useState('SAVE'); + const [isSessionSaved, setIsSessionSaved] = useState(false); + const globalContext = useContext(GlobalContext); + + + const handleSaveSession = async ( + overwrite: boolean, + old_session_id: string | null, + session_name: string + ) => { + try { + const response = await httpPost( + session, + `warehouse/ask/${newSessionId}/save`, + { + session_name, + overwrite, + old_session_id, + } + ); + + if (response.success) { + successToast(`${session_name} saved successfully`, [], globalContext); + setIsSessionSaved(true); + handleNewSession(); } - }; - console.log(modalName, 'modalname'); - return ( - <> - - {/* inside the bottom box we will keep everything */} - - - LLM Summary - {/* info icon */} - - - - - {/* THIS IS THE SUMMARY UI PORTION */} - { + console.log(data, overwrite, "data") + const oldSessionIdToSend = overwrite ? oldSessionMetaInfo?.oldSessionId : null; + handleSaveSession(overwrite, oldSessionIdToSend, data.sessionName); + }; + + // Function to handle copying text + const handleCopyClick = async () => { + const copyRes: boolean = await copyToClipboard(llmSummary); + if (copyRes) { + successToast('Successfully copied to clipboard', [], globalContext); + } else { + errorToast( + 'Some problem with copying. Please try again', + [], + globalContext + ); + } + }; + + + return ( + + + + LLM Summary + + + + {/* Summary UI */} + + dalgo icon + + {llmSummary} + + + {/* Icons */} + + + copy icon + + + + thumbs up icon + + + { + setModalName('FEEDBACK_FORM'); + setIsBoxOpen(true); }} + disabled={!llmSummary} > logout icon - - {' '} - {llmSummary} - - - {/* Copy Icon Button */} - - copy icon - - - {/* Thumbs Up Icon Button */} - - thumbs up icon - - - {/* Thumbs Down Icon Button with onClick */} - { - setModalName('FEEDBACK_FORM'); - setIsBoxOpen(true); - }} - disabled={!llmSummary} - > - thumbs down icon - - - - - - - + - {isBoxOpen && ( - - )} - - ); - } -); + {/* Buttons */} + + + + + + {/* Modal */} + {isBoxOpen && ( + + )} + + + + ); +}; + +// CSS for the container box const customCss = { display: 'flex', boxShadow: '0 4px 8px rgba(9, 37, 64, 0.08)', backgroundColor: '#FFFFFF', borderRadius: '12px', padding: '2rem', - // borderColor: '#FFFFFF', }; - -LLMSummary.displayName = "LLM-summary"; \ No newline at end of file +LLMSummary.displayName = 'LLM-summary'; +export default LLMSummary; diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index 10c4bf33..bc7824a9 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -1,71 +1,48 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useState } from 'react'; import { Box, Button, TextField, Typography, - Dialog, DialogActions, - DialogContent, - DialogTitle, - IconButton, } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; import { httpPost } from '@/helpers/http'; import { useSession } from 'next-auth/react'; import { errorToast, successToast } from '../ToastMessage/ToastHelper'; import { GlobalContext } from '@/contexts/ContextProvider'; +import CustomDialog from '../Dialog/CustomDialog'; +import { useForm, Controller } from 'react-hook-form'; // Import React Hook Form + +// Define the form data type +interface FormData { + sessionName: string; +} export const OverWriteDialog = ({ open, setIsBoxOpen, modalName, - oldSessionId, - newSessionId, - handleNewSession, + onSubmit, }: { open: boolean; modalName: string; - oldSessionId: string; - newSessionId: string; - handleNewSession: any; + onSubmit: any; setIsBoxOpen: (a: boolean) => void; }) => { - const { data: session } = useSession(); - const globalContext = useContext(GlobalContext); - const [textBoxData, setTextBoxData] = useState(''); - const [openModalName, setOpenModalName] = useState(modalName); - const [isSessionSaved, setIsSessionSaved] = useState(false); - const handleClose = () => setIsBoxOpen(false); + const { + control, + handleSubmit, + reset, + formState: { isSubmitting, errors }, + } = useForm({ + defaultValues: { + sessionName: '', + }, + }); - console.log(modalName, 'modalname'); - const handleSaveSession = async ( - overwrite: boolean, - old_session_id: string | null - ) => { - try { - const response = await httpPost( - session, - `warehouse/ask/${newSessionId}/save`, - { - session_name: textBoxData, - overwrite, - old_session_id, - } - ); - console.log(response, 'response'); - //write error condition - if (response.success) { - successToast(`${textBoxData} saved successfully`, [], globalContext); - setIsSessionSaved(true); - handleNewSession(); - } - } catch (err: any) { - console.log(err); - errorToast(err.message, [], globalContext); - } finally { - handleClose(); - } + const handleClose = () => { + reset(); + setIsBoxOpen(false); }; const ModalData: any = { @@ -82,9 +59,7 @@ export const OverWriteDialog = ({ padding: '8px 0', borderRadius: '5px', }, - onClick: () => { - handleSaveSession(false, null); - }, + onClick: handleSubmit((data) => onSubmit(data, false)), // Use handleSubmit from react-hook-form }, { label: 'Cancel', @@ -111,9 +86,7 @@ export const OverWriteDialog = ({ padding: '8px 0', borderRadius: '5px', }, - onClick: () => { - setOpenModalName('CONFIRM_SAVEAS'); - }, + onClick: handleSubmit((data) => onSubmit(data, true)), // Handle form submission }, { label: 'Save as new', @@ -123,9 +96,7 @@ export const OverWriteDialog = ({ padding: '8px 0', borderRadius: '5px', }, - onClick: () => { - handleSaveSession(false, null); - }, + onClick: handleSubmit((data) => onSubmit(data, false)), // Use handleSubmit from react-hook-form }, { label: 'Cancel', @@ -135,7 +106,7 @@ export const OverWriteDialog = ({ padding: '8px 0', borderRadius: '5px', }, - onClick: handleClose, // Use existing handleClose function for the Cancel button + onClick: handleClose, }, ], }, @@ -152,9 +123,7 @@ export const OverWriteDialog = ({ padding: '8px 0', borderRadius: '5px', }, - onClick: () => { - handleSaveSession(true, oldSessionId); //overwriting, opens when clicked overwrite. - }, + onClick: handleSubmit((data) => onSubmit(data, false)), // Use handleSubmit from react-hook-form }, { label: 'Cancel', @@ -186,110 +155,78 @@ export const OverWriteDialog = ({ }, ], }, - UNSAVED_CHANGES: { - mainheading: 'Unsaved changes', - subHeading: - 'You are about to leave this page without saving the changes.\nAll the changes that were made will be lost. Do you wish to continue?', - buttons: [ - { - label: 'Save changes', - variant: 'contained', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', - }, - onClick: () => { - handleSaveSession(false, oldSessionId); - }, - }, - { - label: 'Leave anyway', - variant: 'outlined', - sx: { - width: '6.75rem', - padding: '8px 0', - borderRadius: '5px', - }, - onClick: handleClose, - }, - ], - }, }; - return ( - <> - {/* Dialog Box */} - - {/* Dialog Title with close button */} - - - - {ModalData[openModalName].mainheading} - - - - - - - - {/* Dialog Content */} - - - {ModalData[openModalName].subHeading} - - {/* Input Field */} - - { - setTextBoxData(e.target.value); - }} - /> - - + const FormContent = () => { + return ( + <> + + {ModalData[modalName].subHeading} + + + {/* Using Controller to handle TextField with validation */} + ( + + )} + /> + + + ); + }; - {/* Dialog Actions */} + return ( + {}} + formContent={} + formActions={ - {ModalData[openModalName].buttons.map( - (button: any, index: number) => ( - - ) - )} + {ModalData[modalName].buttons.map((button: any, index: number) => ( + + ))} - - + } + loading={isSubmitting} // Set loading state based on form submission + /> ); }; diff --git a/src/components/DataAnalysis/SavedSession.tsx b/src/components/DataAnalysis/SavedSession.tsx index 1be3eab8..1500a101 100644 --- a/src/components/DataAnalysis/SavedSession.tsx +++ b/src/components/DataAnalysis/SavedSession.tsx @@ -12,6 +12,7 @@ import { Button, TablePagination, CircularProgress, + Typography, } from '@mui/material'; import Image from 'next/image'; @@ -294,7 +295,7 @@ export const SavedSession = memo( }} > - {trimText(row.session_name, 20)} + {trimText(row.session_name, 30)} - { - handlePagination(newPage, pageSize); - }} - onRowsPerPageChange={(e: any) => { - const newPageSize = parseInt(e.target.value, 10); - setPageSize(newPageSize); - setCurrentPageIndex(0); - handlePagination(0, newPageSize); - }} - /> + {!!savedSessions.length && ( + { + handlePagination(newPage, pageSize); + }} + onRowsPerPageChange={(e: any) => { + const newPageSize = parseInt(e.target.value, 10); + setPageSize(newPageSize); + setCurrentPageIndex(0); + handlePagination(0, newPageSize); + }} + /> + )} @@ -373,4 +376,4 @@ export const SavedSession = memo( } ); -SavedSession.displayName = "Saved-Session"; \ No newline at end of file +SavedSession.displayName = 'Saved-Session'; From 1162d42bcca03bc3c86585731eff104595d9b3ea Mon Sep 17 00:00:00 2001 From: himanshudube97 Date: Mon, 9 Sep 2024 18:00:45 +0530 Subject: [PATCH 22/52] added and changed fixes, used the prebuilt components --- src/components/DataAnalysis/LLMSummary.tsx | 56 ++++++++--- src/components/DataAnalysis/OverwriteBox.tsx | 94 +++++++++++++------ src/components/DataAnalysis/SavedSession.tsx | 1 - src/components/DataAnalysis/SqlWrite.tsx | 1 - src/components/DataAnalysis/TopBar.tsx | 2 - src/components/SideDrawer/SideDrawer.tsx | 6 +- src/contexts/ContextProvider.tsx | 7 ++ .../reducers/UnsavedChangesReducer.ts | 17 ++++ src/pages/analysis/data-analysis.tsx | 54 ++++++++--- 9 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 src/contexts/reducers/UnsavedChangesReducer.ts diff --git a/src/components/DataAnalysis/LLMSummary.tsx b/src/components/DataAnalysis/LLMSummary.tsx index ed97b4f3..288edbd0 100644 --- a/src/components/DataAnalysis/LLMSummary.tsx +++ b/src/components/DataAnalysis/LLMSummary.tsx @@ -17,24 +17,23 @@ import { useSession } from 'next-auth/react'; export const LLMSummary = ({ llmSummary, newSessionId, - prompt, oldSessionMetaInfo, handleNewSession, }: { llmSummary: string; newSessionId: string; - prompt: string; oldSessionMetaInfo: any; handleNewSession: any; }) => { const router = useRouter(); - const {data:session} = useSession(); + const { data: session } = useSession(); const [isBoxOpen, setIsBoxOpen] = useState(false); const [modalName, setModalName] = useState('SAVE'); - const [isSessionSaved, setIsSessionSaved] = useState(false); + const [attemptedRoute, setAttemptedRoute] = useState(null); const globalContext = useContext(GlobalContext); + const { dispatch, state } = globalContext?.UnsavedChanges as any; - + //handling save session-> const handleSaveSession = async ( overwrite: boolean, old_session_id: string | null, @@ -53,7 +52,6 @@ export const LLMSummary = ({ if (response.success) { successToast(`${session_name} saved successfully`, [], globalContext); - setIsSessionSaved(true); handleNewSession(); } } catch (err: any) { @@ -63,13 +61,16 @@ export const LLMSummary = ({ } }; - const onSubmit = (data:any, overwrite:boolean) => { - console.log(data, overwrite, "data") - const oldSessionIdToSend = overwrite ? oldSessionMetaInfo?.oldSessionId : null; + // submitting the session name -> + const onSubmit = (data: any, overwrite: boolean) => { + console.log(data, overwrite, 'data'); + const oldSessionIdToSend = overwrite + ? oldSessionMetaInfo?.oldSessionId + : null; handleSaveSession(overwrite, oldSessionIdToSend, data.sessionName); }; - // Function to handle copying text + // Function to handle copying text -> const handleCopyClick = async () => { const copyRes: boolean = await copyToClipboard(llmSummary); if (copyRes) { @@ -83,6 +84,38 @@ export const LLMSummary = ({ } }; + // checks for the route change-> + //cover both cases, while editing, and the first time too wehn the user creats a analysis. + useEffect(() => { + const handleRouteChange = (url: any) => { + if ( + (oldSessionMetaInfo.oldSessionId && newSessionId && state === false) || + (newSessionId && !oldSessionMetaInfo.oldSessionId && state === false) + ) { + router.events.emit('routeChangeError'); + setModalName('UNSAVED_CHANGES'); + setIsBoxOpen(true); + dispatch({ type: 'SET_UNSAVED_CHANGES' }); + setAttemptedRoute(url); + throw 'Unsaved changes, route change aborted'; + } + }; + + router.events.on('routeChangeStart', handleRouteChange); + + return () => { + router.events.off('routeChangeStart', handleRouteChange); + dispatch({ type: 'CLEAR_UNSAVED_CHANGES' }); + }; + }, [router, oldSessionMetaInfo.oldSessionId, state, newSessionId]); + + //the unsaved modal function-> + const onConfirmNavigation = () => { + if (attemptedRoute) { + dispatch({ type: 'SET_UNSAVED_CHANGES' }); + router.push(attemptedRoute); + } + }; return ( @@ -209,9 +242,10 @@ export const LLMSummary = ({ setIsBoxOpen={setIsBoxOpen} modalName={modalName} onSubmit={onSubmit} + onConfirmNavigation={onConfirmNavigation} + setModalName={setModalName} /> )} - ); diff --git a/src/components/DataAnalysis/OverwriteBox.tsx b/src/components/DataAnalysis/OverwriteBox.tsx index bc7824a9..1e9c9143 100644 --- a/src/components/DataAnalysis/OverwriteBox.tsx +++ b/src/components/DataAnalysis/OverwriteBox.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React from 'react'; import { Box, Button, @@ -6,12 +6,8 @@ import { Typography, DialogActions, } from '@mui/material'; -import { httpPost } from '@/helpers/http'; -import { useSession } from 'next-auth/react'; -import { errorToast, successToast } from '../ToastMessage/ToastHelper'; -import { GlobalContext } from '@/contexts/ContextProvider'; import CustomDialog from '../Dialog/CustomDialog'; -import { useForm, Controller } from 'react-hook-form'; // Import React Hook Form +import { useForm, Controller } from 'react-hook-form'; // Define the form data type interface FormData { @@ -23,10 +19,14 @@ export const OverWriteDialog = ({ setIsBoxOpen, modalName, onSubmit, + onConfirmNavigation, + setModalName, }: { open: boolean; modalName: string; onSubmit: any; + onConfirmNavigation: any; + setModalName: any; setIsBoxOpen: (a: boolean) => void; }) => { const { @@ -155,6 +155,39 @@ export const OverWriteDialog = ({ }, ], }, + UNSAVED_CHANGES: { + mainheading: 'Unsaved changes', + subHeading: + 'You are about to leave this page without saving the changes.\nAll the changes that were made will be lost. Do you wish to continue?', + // rowsNum: 5, + label: 'Unsaved changes', + buttons: [ + { + label: 'Save changes', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + setModalName('OVERWRITE'); + }, + }, + { + label: 'Leave anyway', + variant: 'contained', + sx: { + width: '6.75rem', + padding: '8px 0', + borderRadius: '5px', + }, + onClick: () => { + onConfirmNavigation(); + }, + }, + ], + }, }; const FormContent = () => { @@ -169,28 +202,29 @@ export const OverWriteDialog = ({ > {ModalData[modalName].subHeading} - - {/* Using Controller to handle TextField with validation */} - ( - - )} - /> - + {modalName !== 'UNSAVED_CHANGES' && ( + + ( + + )} + /> + + )} ); }; @@ -202,7 +236,7 @@ export const OverWriteDialog = ({ title={ModalData[modalName].mainheading} show={open} handleClose={handleClose} - handleSubmit={()=>{}} + handleSubmit={() => {}} formContent={} formActions={ - {ModalData[modalName].buttons.map((button: any, index: number) => ( + {ModalData[modalName]?.buttons.map((button: any, index: number) => ( @@ -261,4 +267,3 @@ const customCss = { }; LLMSummary.displayName = 'LLM-summary'; - diff --git a/src/components/DataAnalysis/SqlWrite.tsx b/src/components/DataAnalysis/SqlWrite.tsx index e3312c0f..ed43116b 100644 --- a/src/components/DataAnalysis/SqlWrite.tsx +++ b/src/components/DataAnalysis/SqlWrite.tsx @@ -224,8 +224,17 @@ export const SqlWrite = memo( flex: '1 1 auto', backgroundColor: selectedDefaultPrompt === defaultPrompts.prompt - ? '#05443e' - : '#00897B', + ? '#00897B' + : '#F5FAFA', + color: + selectedDefaultPrompt === defaultPrompts.prompt + ? '#FFFFFF' + : '#3C4C63', + + '&:hover': { + backgroundColor: '#00897B', + color: '#FFFFFF', + }, }} onClick={() => { handlePromptSelection(defaultPrompts.prompt); @@ -328,6 +337,13 @@ export const SqlWrite = memo( width: '100%', height: '2.75rem', borderRadius: '6px', + color: '#3C4C63', + backgroundColor: customPromptToggle ? '#05443e' : '#F5FAFA', + + '&:hover': { + backgroundColor: '#00897B', + color: '#FFFFFF', + }, }} onClick={() => { setValue('defaultPrompt', ''); diff --git a/src/components/DataAnalysis/TopBar.tsx b/src/components/DataAnalysis/TopBar.tsx index cd2346e0..dacfce93 100644 --- a/src/components/DataAnalysis/TopBar.tsx +++ b/src/components/DataAnalysis/TopBar.tsx @@ -1,5 +1,6 @@ import { Box, Button, Typography } from '@mui/material'; import InfoTooltip from '../UI/Tooltip/Tooltip'; +import Folder from '@mui/icons-material/Folder'; export const TopBar = ({ handleOpenSavedSession, handleNewSession }: any) => { return ( <> @@ -35,13 +36,25 @@ export const TopBar = ({ handleOpenSavedSession, handleNewSession }: any) => { flexWrap: 'wrap', }} > - +