Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAN-822]: sidebar status persisted #1229

Merged
merged 71 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
042c20c
feat(pandasai_server): pandasai server code commit
ArslanSaleem May 30, 2024
6954fae
fix(docker-compose): add pandasbi backend in docker
ArslanSaleem May 30, 2024
cc9437e
fix(pandasai-lint): sort linting errors
ArslanSaleem May 31, 2024
a934925
refactor: rename modle file name
ArslanSaleem May 31, 2024
c3f46e4
feat(chat): adding chat endpoint
ArslanSaleem May 31, 2024
ddba3cd
fix: remove some keywords from spellcheck
ArslanSaleem May 31, 2024
2d67e32
fix: poetry lock file
ArslanSaleem Jun 3, 2024
fa30418
me api integrated
shahrukh802 Jun 3, 2024
87d3f43
chat api integrated
shahrukh802 Jun 3, 2024
f64212a
renamed, fix and add documentation
ArslanSaleem Jun 3, 2024
614f278
env for windows added
shahrukh802 Jun 3, 2024
916bf61
workspace replaced
shahrukh802 Jun 3, 2024
db4840c
fix: add conversation id to response
ArslanSaleem Jun 3, 2024
ad13425
Merge branch 'feat/pandasai-server' of https://github.com/gventuri/pa…
ArslanSaleem Jun 3, 2024
dd74a82
feat(conversation): return all user conversations
ArslanSaleem Jun 3, 2024
082df8a
fix: should be equal equal
ArslanSaleem Jun 3, 2024
7801577
feat(pandasai_server): pandasai server code commit (#1189)
ArslanSaleem Jun 3, 2024
fc770c4
get all datasets endpoint completed
shahrukh802 Jun 3, 2024
9a15e6f
Merge branch 'release/v2.2' of github.com:Sinaptik-AI/pandas-ai into …
shahrukh802 Jun 3, 2024
797bc9b
merge conflicts fixed
shahrukh802 Jun 3, 2024
a2c6e4d
feat(conversation_messages): return conversation messages (#1196)
ArslanSaleem Jun 3, 2024
73df4d5
get all datasets endpoint completed (#1197)
shahrukh802 Jun 3, 2024
8137040
chore: update poetry.lock
gventuri Jun 3, 2024
7585a4f
chore: add pgdata to gitignore
gventuri Jun 3, 2024
06f4c13
chore: fix postgres url in the server .env example
gventuri Jun 3, 2024
8fbe8aa
chore: add .env.example for the client
gventuri Jun 3, 2024
b028813
fix: add rollbar
gventuri Jun 4, 2024
d3afd66
fix: wrong redirects
gventuri Jun 4, 2024
1a8938c
fix: docker compose to wait for postgres before starting (#1198)
ArslanSaleem Jun 4, 2024
1748caa
fix: response message should be value for strings and numbers (#1199)
ArslanSaleem Jun 4, 2024
7333dbd
docs: mention the platform in the docs
gventuri Jun 4, 2024
7148e0e
style: hide rightbar for now
gventuri Jun 4, 2024
3a4ec0f
style: move the "new chat" button next to chat
gventuri Jun 4, 2024
0e8cde2
[PAN-816]: Past conversations integrated and workspace removed (#1200)
shahrukh802 Jun 4, 2024
aa90622
style: remove tooltip from the sidebar
gventuri Jun 4, 2024
287614e
style: clean up the UI
gventuri Jun 4, 2024
0bc957c
chore: fix typo in volume name
gventuri Jun 4, 2024
ffbbc52
conversation actions removed
shahrukh802 Jun 4, 2024
f0d5a95
conversation actions removed (#1201)
shahrukh802 Jun 4, 2024
882a7cd
fix: filter out empty conversations
gventuri Jun 4, 2024
371ae78
docs: add platform in the docs
gventuri Jun 5, 2024
b8cc32b
get users by workspace id api added
shahrukh802 Jun 5, 2024
6d1d106
Merge branch 'feat/removeactions' into feat/PAN-802
shahrukh802 Jun 5, 2024
e2ee3e2
Merge branch 'release/v2.2' into feat/PAN-801
shahrukh802 Jun 5, 2024
fb053bb
docs: add docs about the platform
gventuri Jun 5, 2024
f88635a
pydantic response for workspace user added
shahrukh802 Jun 5, 2024
a682ff8
Merge pull request #1205 from Sinaptik-AI/feat/PAN-802
ArslanSaleem Jun 5, 2024
9359dbd
Merge branch 'release/v2.2' into feat/PAN-801
shahrukh802 Jun 5, 2024
dbae6b6
workspace datasets endpoint added
shahrukh802 Jun 5, 2024
b4c58e7
archive conversation api added (#1209)
shahrukh802 Jun 5, 2024
59d05e9
conflicts fixed
shahrukh802 Jun 6, 2024
19a837a
Merge pull request #1207 from Sinaptik-AI/feat/PAN-801
ArslanSaleem Jun 6, 2024
d3d325b
[PAN-820]: archive api integrated on frontend (#1210)
shahrukh802 Jun 6, 2024
52e5f70
chore: add link about the roadmap
gventuri Jun 6, 2024
bff29cb
past conversation issues fixed
shahrukh802 Jun 6, 2024
8283ce9
[PAN-824]: Ui stuck fixed (#1215)
shahrukh802 Jun 7, 2024
763e009
Merge pull request #1213 from Sinaptik-AI/bug/PAN-828
ArslanSaleem Jun 7, 2024
58510d2
style: ctas in the sidebar fade out on collapse
gventuri Jun 7, 2024
999ef75
scroll to bottom bug fix (#1217)
shahrukh802 Jun 7, 2024
3329aa9
tests(pandasai): write python test cases (#1216)
ArslanSaleem Jun 7, 2024
8ab311f
new conversation not adding to sidebar fixed
shahrukh802 Jun 10, 2024
6f1e229
Merge pull request #1218 from Sinaptik-AI/bug/PAN-825
ArslanSaleem Jun 10, 2024
96f11e1
fix: frontend docker build (#1219)
ArslanSaleem Jun 10, 2024
9b20804
Merge branch 'main' into release/v2.2
ArslanSaleem Jun 12, 2024
4cc3579
merge main to release
ArslanSaleem Jun 12, 2024
856fdc8
dataframe table design improved
shahrukh802 Jun 12, 2024
e105287
dataframe table design improved (#1227)
shahrukh802 Jun 13, 2024
98661ee
sidebar status persisted
shahrukh802 Jun 13, 2024
419ffca
Merge branch 'release/v2.2' into feature/PAN-822
shahrukh802 Jun 13, 2024
55464b5
merge conflicts fixed
shahrukh802 Jun 13, 2024
accacbb
scroll added to table
shahrukh802 Jun 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"react/no-unescaped-entities": ["error", { "forbid": [">", "}"] }],
"@typescript-eslint/no-explicit-any": "off",
"no-useless-catch": "off",
"react-hooks/exhaustive-deps": 0
"react-hooks/exhaustive-deps": 0,
"react/prop-types": "off"
}
}
1 change: 0 additions & 1 deletion client/Providers/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import "styles/globals.css";
import "styles/App.css";
import "styles/multi-range-slider.css";
import "react-toastify/dist/ReactToastify.css";
import "react-tooltip/dist/react-tooltip.css";

const _NoSSR = ({ children }) => <React.Fragment>{children}</React.Fragment>;
const NoSSR = dynamic(() => Promise.resolve(_NoSSR), {
Expand Down
18 changes: 8 additions & 10 deletions client/components/AddUserModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { useAddSpaceUsers, useDeleteSpaceUsers } from "hooks/useSpaces";
import { Loader } from "components/loader/Loader";
import { toast } from "react-toastify";
import { useGetMembersList, useGetOrganizations } from "hooks/useOrganizations";
import { Tooltip } from "react-tooltip";
import { Input } from "../ui/input";
import AppTooltip from "../AppTooltip";

interface ISpaceUser {
space_id: string;
Expand Down Expand Up @@ -111,15 +111,13 @@ const AddUserModal = ({ setIsModelOpen, spaceUsers, spaceId }: IProps) => {
className="cursor-pointer min-w-[50px] border-white/0 py-3 pr-4 pl-4 flex"
onClick={() => handleDeleteSpaceUser(user?.user_id)}
>
<AiFillDelete id="deleteIcon" color="#ccc" size="1.5em" />

<Tooltip
anchorSelect="#deleteIcon"
className="z-10"
opacity={1}
>
You cannot remove the sole user from this workspace
</Tooltip>
<AppTooltip text="You cannot remove the sole user from this workspace">
<AiFillDelete
id="deleteIcon"
color="#ccc"
size="1.5em"
/>
</AppTooltip>
</span>
) : (
<span
Expand Down
28 changes: 28 additions & 0 deletions client/components/AppTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";
import React from "react";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";

interface IProps {
text: string;
children: React.ReactNode;
}

const AppTooltip = ({ text, children }: IProps) => {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>{children}</TooltipTrigger>
<TooltipContent>
<p>{text}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};

export default AppTooltip;
3 changes: 1 addition & 2 deletions client/components/ChatScreen/AIChatBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const AIChatBubble = ({ chat, lastIndex }: IProps) => {
/>
</div>

<div className="flex flex-1 flex-col">
<div className="flex w-full flex-col">
<span className="dark:text-white font-bold text-lg">PandaBI</span>
<div
className={`break-all text-sm md:text-[15px] font-medium w-auto overflow-visible dark:text-white
Expand All @@ -58,7 +58,6 @@ const AIChatBubble = ({ chat, lastIndex }: IProps) => {
<ChatDataFrame
chatResponse={response}
chatId={chat.id}
index={indx}
key={chat?.id}
/>
</>
Expand Down
242 changes: 62 additions & 180 deletions client/components/ChatScreen/ChatDataFrame.tsx
Original file line number Diff line number Diff line change
@@ -1,202 +1,84 @@
"use client";
import { FetchDataframe } from "services/chat";
import { ChatResponseItem } from "@/types/chat-types";
import React, { useState, useRef, useEffect } from "react";
import { FaChevronDown, FaChevronUp } from "react-icons/fa";
import { toast } from "react-toastify";
import { Grid } from "gridjs";
import DownloadIcon from "../Icons/DownloadIcon";
import SearchIcon from "../Icons/SearchIcon";
import { useAppStore } from "@/store";
import AppTooltip from "../AppTooltip";
import { convertToCSV } from "@/utils/convertToCSV";
import "gridjs/dist/theme/mermaid.css";

interface IProps {
chatResponse: ChatResponseItem;
index: number;
chatId: string;
}

const StyledRecord = ({ record }: { record: string }) => {
if (!record) return record;

if (record === "true" || record === "True") {
return (
<span className="text-green-500">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 inline"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 13l4 4L19 7"
/>
</svg>
</span>
);
} else if (record === "false" || record === "False") {
return (
<span className="text-red-500">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 inline"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</span>
);
} else if (record.includes("http") || record.includes("www")) {
return (
<a
href={record}
target="_blank"
rel="noreferrer noopener"
className="text-[#86ade4] hover:underline"
>
{record}
</a>
);
} else if (record.includes("@") && record.includes(".")) {
return (
<a href={`mailto:${record}`} className="text-[#86ade4] hover:underline">
{record}
</a>
);
} else {
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (dateRegex.test(record)) {
const date = new Date(record);
const options: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
};
return date.toLocaleDateString("en-US", options);
} else {
return record;
}
}
};

const ChatDataFrame = ({ chatResponse, index, chatId }: IProps) => {
const [expandedCardId, setExpandedCardId] = useState(null);
const [contentHeight, setContentHeight] = useState("300px");
const [isDownloading, setIsDownloading] = useState(false);
const ChatDataFrame = ({ chatResponse, chatId }: IProps) => {
const contentRef = useRef(null);
const [search, setSearch] = useState(false);
const darkMode = useAppStore((state) => state.darkMode);

const grid = new Grid({
columns: chatResponse?.value?.headers,
data: chatResponse?.value?.rows,
sort: true,
search: true,
pagination: {
limit: 10,
summary: false,
},
style: {
table: {
"white-space": "nowrap",
},
},
height: "600px",
resizable: true,
});

useEffect(() => {
if (expandedCardId === index && contentRef.current) {
setContentHeight(`${contentRef.current.scrollHeight}px`);
} else {
setContentHeight("300px");
}
}, [expandedCardId, index]);
grid.render(contentRef.current);
});

const handleSearch = () => {
const gridJsHead = contentRef.current.querySelector(".gridjs-head");

const handleToggleExpand = (index) => {
setExpandedCardId((prevId) => (prevId === index ? null : index));
if (gridJsHead) {
gridJsHead.style.display = search ? "none" : "block";
setSearch(!search);
}
};

const handleDownload = async (id: string) => {
setIsDownloading(true);
await FetchDataframe(id)
.then((response) => {
const fileUrl = response?.data?.data?.download_url;
const link = document.createElement("a");
link.href = fileUrl;
link.setAttribute("download", `dataframe-${id}`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch((error) => {
toast.error(
error?.response?.data?.message
? error.response.data.message
: error.message
);
})
.finally(() => setIsDownloading(false));
const handleDownload = async () => {
const { headers, rows } = chatResponse.value;
const csvData = convertToCSV(headers, rows);
const blob = new Blob([csvData], { type: "text/csv" });
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("download", `dataframe-${chatId}.csv`);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
};

return (
<div className="mt-2">
<div
ref={contentRef}
className={`relative bg-white dark:bg-[#333333] rounded-[20px] px-4 py-2 custom-scroll overflow-hidden overflow-x-auto transition-all`}
style={{ maxHeight: contentHeight, height: "auto" }}
>
<table className="overflow-auto w-full">
<thead>
<tr className="!border-px !border-gray-400 uppercase p-2">
{chatResponse?.value?.headers?.map((item, index) => (
<th
key={index}
className="cursor-pointer border-b p-2 text-center border-solid border-r last:border-r-0 text-xs min-w-[100px]"
>
{item.split("_").join(" ")}
</th>
))}
</tr>
</thead>
<tbody>
{chatResponse?.value?.rows?.map((rows, index) => (
<tr className="cursor-pointer" key={index}>
{Object.values(rows).map((item, index) => (
<td
key={index}
className="text-center border-solid border-r dark:border-white border-[rgba(0,0,0,0.10)] last:border-r-0 pt-3"
>
<StyledRecord record={`${item}`} />
</td>
))}
</tr>
))}
</tbody>
</table>
{chatResponse?.value?.rows?.length > 3 && (
<div
className={`absolute bottom-0 left-0 right-0 h-20 bg-gradient-to-t from-white dark:from-[#191919] to-transparent pointer-events-none ${
expandedCardId !== index ? "opacity-100" : "opacity-0"
} transition-all`}
></div>
)}

{expandedCardId === index && (
<div className="text-center mt-6">
<button
className="cursor-pointer bg-[#191919] h-[24px] text-xs text-white font-bold rounded-full px-3 py-1"
onClick={() => {
handleDownload(chatId);
}}
>
{isDownloading ? "Downloading..." : "Download the full table"}
</button>
</div>
)}
</div>
<div className="text-center mt-2 flex flex-col gap-2 items-center justify-center">
{chatResponse?.value?.rows?.length > 3 && (
<button
className="h-6 w-6 flex items-center justify-center text-white bg-[#191919] rounded-full"
onClick={() => handleToggleExpand(index)}
>
{expandedCardId === index ? (
<FaChevronUp size="1em" />
) : (
<FaChevronDown size="1em" />
)}
</button>
)}
<div className="flex flex-col mt-2">
<div className="flex justify-end">
<div className="cursor-pointer" onClick={handleSearch}>
<AppTooltip text="Search">
<SearchIcon color={darkMode ? "#fff" : "#000"} />
</AppTooltip>
</div>
<div className="cursor-pointer" onClick={handleDownload}>
<AppTooltip text="Download">
<DownloadIcon color={darkMode ? "#fff" : "#000"} />
</AppTooltip>
</div>
</div>
<div ref={contentRef} className={`grid-container${chatId}`} />
</div>
);
};
Expand Down
20 changes: 20 additions & 0 deletions client/components/Icons/DownloadIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

const DownloadIcon = ({ color = "white" }: { color?: string }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 15.577L8.461 12.039L9.169 11.319L11.5 13.65V5H12.5V13.65L14.83 11.32L15.539 12.039L12 15.577ZM6.616 19C6.15533 19 5.771 18.846 5.463 18.538C5.155 18.23 5.00067 17.8453 5 17.384V14.961H6V17.384C6 17.538 6.064 17.6793 6.192 17.808C6.32 17.9367 6.461 18.0007 6.615 18H17.385C17.5383 18 17.6793 17.936 17.808 17.808C17.9367 17.68 18.0007 17.5387 18 17.384V14.961H19V17.384C19 17.8447 18.846 18.229 18.538 18.537C18.23 18.845 17.8453 18.9993 17.384 19H6.616Z"
fill={color}
/>
</svg>
);
};

export default DownloadIcon;
Loading
Loading