diff --git a/src/frontend/src/App.css b/src/frontend/src/App.css index 095c63bd7..6aa681415 100644 --- a/src/frontend/src/App.css +++ b/src/frontend/src/App.css @@ -90,3 +90,12 @@ body { .jv-indent::-webkit-scrollbar-thumb:hover { background-color: #bbb !important; } + +.custom-hover { + transition: background-color 0.5s ease; +} + +.custom-hover:hover { + background-color: rgba(99, 102, 241, 0.1); /* Medium indigo color with 20% opacity */ +} + diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index c8d338956..4b0b752e1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -521,10 +521,10 @@ export default function GenericNode({ ) : !validationStatus ? ( {STATUS_BUILD} ) : ( -
+
{lastRunTime && ( -
+
{RUN_TIMESTAMP_PREFIX}
{lastRunTime} @@ -532,19 +532,19 @@ export default function GenericNode({
)}
-
+
Duration:
-
+
{validationStatus?.data.duration}

- + Output -
+
{validationString.split("\n").map((line, index) => ( -
{line}
+
{line}
))}
diff --git a/src/frontend/src/components/IOview/index.tsx b/src/frontend/src/components/IOview/index.tsx index 73f0a068e..ced31a177 100644 --- a/src/frontend/src/components/IOview/index.tsx +++ b/src/frontend/src/components/IOview/index.tsx @@ -20,7 +20,12 @@ import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs"; -export default function IOView({ children, open, setOpen }): JSX.Element { +export default function IOView({ children, open, setOpen, disable }: { + children: JSX.Element; + open: boolean; + setOpen: (open: boolean) => void; + disable?: boolean; +}): JSX.Element { const inputs = useFlowStore((state) => state.inputs).filter( (input) => input.type !== "ChatInput" ); @@ -98,6 +103,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element { size={haveChat ? (selectedTab === 0 ? "large-thin" : "large") : "small"} open={open} setOpen={setOpen} + disable={disable} > {children} {/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */} diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index da612340a..3d3a01562 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -1,14 +1,26 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import useFlowStore from "../../stores/flowStore"; import { ChatType } from "../../types/chat"; import IOView from "../IOview"; import ChatTrigger from "../ViewTriggers/chat"; +import { Transition } from "@headlessui/react"; +import ForwardedIconComponent from "../genericIconComponent"; +import { Separator } from "../ui/separator"; +import ShareModal from "../../modals/shareModal"; +import { useStoreStore } from "../../stores/storeStore"; +import useFlowsManagerStore from "../../stores/flowsManagerStore"; +import { classNames } from "../../utils/utils"; +import ApiModal from "../../modals/ApiModal"; -export default function Chat({ flow }: ChatType): JSX.Element { +export default function FlowToolbar({ flow }: ChatType): JSX.Element { const [open, setOpen] = useState(false); const flowState = useFlowStore((state) => state.flowState); const nodes = useFlowStore((state) => state.nodes); const hasIO = useFlowStore((state) => state.hasIO); + const hasStore = useStoreStore((state) => state.hasStore); + const validApiKey = useStoreStore((state) => state.validApiKey); + const currentFlow = useFlowsManagerStore((state) => state.currentFlow); + const hasApiKey = useStoreStore((state) => state.hasApiKey); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -29,16 +41,102 @@ export default function Chat({ flow }: ChatType): JSX.Element { const prevNodesRef = useRef(); + const ModalMemo = useMemo( + () => ( + + + + ), + [hasApiKey, validApiKey, currentFlow, hasStore] + ); + return ( <> -
- {/* */} - {hasIO && ( - - + +
+
+
+ {hasIO ? ( + +
+ + Run +
+ ) : ( +
+ + Run +
)} +
+
+ +
+
+ {currentFlow && currentFlow.data && ( + +
+ + API +
+
+ )} +
+
+ +
+
+
{ModalMemo}
+
+
+
); } diff --git a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx index 9bff70924..b2f1bc3e2 100644 --- a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx +++ b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx @@ -18,6 +18,9 @@ import { cn } from "../../../../utils/utils"; import ShadTooltip from "../../../ShadTooltipComponent"; import IconComponent from "../../../genericIconComponent"; import { Button } from "../../../ui/button"; +import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants"; +import ExportModal from "../../../../modals/exportModal"; +import { useStoreStore } from "../../../../stores/storeStore"; export const MenuBar = ({ removeFunction, @@ -32,7 +35,9 @@ export const MenuBar = ({ const saveLoading = useFlowsManagerStore((state) => state.saveLoading); const [openSettings, setOpenSettings] = useState(false); const n = useFlowStore((state) => state.nodes); - + const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow); + const hasApiKey = useStoreStore((state) => state.hasApiKey); + const validApiKey = useStoreStore((state) => state.validApiKey); const navigate = useNavigate(); const isBuilding = useFlowStore((state) => state.isBuilding); @@ -100,7 +105,28 @@ export const MenuBar = ({ /> Settings - + { + uploadFlow({ newProject: false, isComponent: false }).catch( + (error) => { + setErrorData({ + title: UPLOAD_ERROR_ALERT, + list: [error], + }); + } + ); + }} + > + + Import + + +
+ + Export +
+
{ undo(); diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index d740129e4..91299ec6f 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -12,7 +12,6 @@ import ReactFlow, { updateEdge, } from "reactflow"; import GenericNode from "../../../../CustomNodes/GenericNode"; -import Chat from "../../../../components/chatComponent"; import { INVALID_SELECTION_ERROR_ALERT, UPLOAD_ALERT_LIST, @@ -38,6 +37,7 @@ import { getRandomName, isWrappedWithClass } from "../../../../utils/utils"; import ConnectionLineComponent from "../ConnectionLineComponent"; import SelectionMenu from "../SelectionMenuComponent"; import ExtraSidebar from "../extraSidebarComponent"; +import FlowToolbar from "../../../../components/chatComponent"; const nodeTypes = { genericNode: GenericNode, @@ -481,7 +481,7 @@ export default function Page({ }} /> - {!view && } + {!view && }
) : ( <> diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx index 299507bbd..565192709 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx @@ -235,66 +235,6 @@ export default function ExtraSidebar(): JSX.Element { return (
-
- {hasStore && validApiKey && ( - -
{ModalMemo}
-
- )} -
- - - -
- {(!hasApiKey || !validApiKey) && ( - -
{ExportMemo}
-
- )} - -
- {currentFlow && currentFlow.data && ( - - - - )} -
-
-
-
handleBlur()} @@ -318,7 +258,7 @@ export default function ExtraSidebar(): JSX.Element { />
- +
{Object.keys(dataFilter) .sort(sortKeys) diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx index f33e97a1d..7d468b4ba 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx @@ -43,6 +43,7 @@ export const SidebarDraggableComponent = forwardRef( const deleteComponent = useFlowsManagerStore( (state) => state.deleteComponent ); + const version = useDarkStore((state) => state.version); const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 }); const popoverRef = useRef(null); diff --git a/src/frontend/src/style/applies.css b/src/frontend/src/style/applies.css index cca804fc7..9f88a6c43 100644 --- a/src/frontend/src/style/applies.css +++ b/src/frontend/src/style/applies.css @@ -69,7 +69,7 @@ @apply flex h-full w-[14.5rem] flex-col overflow-hidden border-r scrollbar-hide; } .side-bar-search-div-placement { - @apply relative mx-auto mb-2 mt-2 flex items-center; + @apply relative mx-auto mb-2 mt-2 flex items-center py-3; } .side-bar-components-icon { @apply h-6 w-4 text-ring; @@ -114,7 +114,10 @@ @apply pointer-events-none; } .extra-side-bar-buttons { - @apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out; + @apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground transition-all duration-500 ease-in-out; + } + .header-menubar-item { + @apply relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 cursor-pointer; } .extra-side-bar-buttons:hover { @apply hover:bg-muted; @@ -495,7 +498,7 @@ @apply flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium; } .header-menu-bar-display { - @apply flex max-w-[120px] cursor-pointer items-center gap-2 lg:max-w-[200px]; + @apply flex max-w-[115px] cursor-pointer items-center gap-2 lg:max-w-[145px]; } .header-menu-flow-name { @apply flex-1 truncate; diff --git a/src/frontend/src/style/index.css b/src/frontend/src/style/index.css index fb4242661..e744fb503 100644 --- a/src/frontend/src/style/index.css +++ b/src/frontend/src/style/index.css @@ -50,6 +50,9 @@ --component-icon: #d8598a; --flow-icon: #2f67d0; + --hover: #F2F4F5; + --disabled-run: #6366f1; + /* Colors that are shared in dark and light mode */ --blur-shared: #151923de; @@ -69,6 +72,8 @@ --background: 224 35% 7.5%; /* hsl(224 40% 10%) */ --foreground: 213 31% 80%; /* hsl(213 31% 91%) */ --ice: #60A5FA; + --hover: #1A202E; + --disabled-run: #6366f1; --muted: 223 27% 11%; /* hsl(223 27% 11%) */ --muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */ diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 4751a05d6..7ebcda3c2 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -32,6 +32,7 @@ import { Cpu, Database, Delete, + Dot, Download, DownloadCloud, Edit, @@ -478,4 +479,5 @@ export const nodeIconsLucide: iconsType = { Bot, Delete, Command, + Dot, }; diff --git a/src/frontend/tailwind.config.js b/src/frontend/tailwind.config.js index 2e2781df7..540289fc8 100644 --- a/src/frontend/tailwind.config.js +++ b/src/frontend/tailwind.config.js @@ -87,8 +87,8 @@ module.exports = { "beta-foreground": "var(--beta-foreground)", "chat-bot-icon": "var(--chat-bot-icon)", "chat-user-icon": "var(--chat-user-icon)", - ice: "var(--ice)", - + "ice": "var(--ice)", + hover: "var(--hover)", white: "var(--white)", border: "hsl(var(--border))", input: "hsl(var(--input))",