From de7b23ea934ca095869067497a43ba46ee8e6c24 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:54:43 -0300 Subject: [PATCH] fix: improve notes functionality, update theme colors definition and resolve ui and ux small bugs (#4414) * Fixed background blur overlay color on dialogs * Try to fix f5 error * Fix text color of notes * Fix bg color of nodenode to first one available if not existent * Removed unused imports * Added new node colors * Updated color of placeholder note node * Fixed notes to appear as soon as when the add button is clicked * Added transparent option to notes * Fixed editor design * Fix design of notes editor * Update text color on the note node description * Added canvas dot variable * Added size and gap definition to background dots * Updated emerald colors and badge * used correct badges on tableAutoCellRender * Used correct colors on the component global variable badge * Fix color on light mode * Fixed emerald color on the status of component * Applied static pink to active icons on navs * Make sidebar narrower * Updated size of / * Fixed Beta and Legacy badges * Fixed position of chevron * Fixed node name input * Updated clear search button * Updated color for grid dots * Updated sidebar filter color * Added chat input check * Fixed sorting of flow sidebar component * Fix canvas color * Updated sticky notes test * Fixed tests * Fixed test --- src/frontend/index.html | 1 + .../components/NodeDescription/index.tsx | 13 +- .../GenericNode/components/NodeName/index.tsx | 11 +- .../handleRenderComponent/index.tsx | 11 +- .../src/CustomNodes/GenericNode/index.tsx | 6 +- .../NoteNode/NoteToolbarComponent/index.tsx | 16 +- .../src/CustomNodes/NoteNode/index.tsx | 28 +- .../components/popover/index.tsx | 9 +- .../components/tableAutoCellRender/index.tsx | 12 +- src/frontend/src/components/ui/badge.tsx | 9 +- .../components/ui/dialog-with-no-close.tsx | 2 +- src/frontend/src/components/ui/dialog.tsx | 2 +- src/frontend/src/components/ui/sheet.tsx | 2 +- src/frontend/src/constants/constants.ts | 21 +- .../src/modals/saveChangesModal/index.tsx | 2 +- .../components/navComponent/index.tsx | 2 +- .../components/PageComponent/index.tsx | 53 ++- .../sidebarFilterComponent/index.tsx | 11 +- .../sidebarDraggableComponent/index.tsx | 209 ++++++----- .../components/flowSidebarComponent/index.tsx | 355 ++++++++++-------- .../shortcutDisplay/index.tsx | 2 +- src/frontend/src/pages/FlowPage/index.tsx | 2 +- src/frontend/src/style/classes.css | 22 +- src/frontend/src/style/index.css | 54 +-- src/frontend/tailwind.config.mjs | 51 +-- .../tests/core/features/group.spec.ts | 5 +- .../extended/features/sticky-notes.spec.ts | 13 +- 27 files changed, 518 insertions(+), 406 deletions(-) diff --git a/src/frontend/index.html b/src/frontend/index.html index 90c8c613b..ff9e78430 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -1,6 +1,7 @@ + diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx index e3e5f9181..48d1e6d8b 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx @@ -11,6 +11,7 @@ export default function NodeDescription({ selected, nodeId, emptyPlaceholder = "Double Click to Edit Description", + placeholderClassName, charLimit, inputClassName, mdClassName, @@ -20,6 +21,7 @@ export default function NodeDescription({ selected: boolean; nodeId: string; emptyPlaceholder?: string; + placeholderClassName?: string; charLimit?: number; inputClassName?: string; mdClassName?: string; @@ -62,7 +64,8 @@ export default function NodeDescription({ className={cn( !inputDescription ? "overflow-auto" : "", hasScroll ? "nowheel" : "", - charLimit ? "px-2" : "", + charLimit ? "px-2 pb-4" : "", + "w-full", )} > {inputDescription ? ( @@ -114,10 +117,11 @@ export default function NodeDescription({ {charLimit && (
= charLimit ? "text-error" : "text-primary", + placeholderClassName, )} data-testid="note_char_limit" > @@ -130,8 +134,9 @@ export default function NodeDescription({ data-testid="generic-node-desc" ref={overflowRef} className={cn( - "nodoubleclick generic-node-desc-text h-full cursor-text text-[13px] word-break-break-word dark:text-note-placeholder", + "nodoubleclick generic-node-desc-text h-full cursor-text text-[13px] word-break-break-word", description === "" || !description ? "font-light italic" : "", + placeholderClassName, )} onDoubleClick={(e) => { setInputDescription(true); @@ -144,7 +149,7 @@ export default function NodeDescription({ diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeName/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeName/index.tsx index 5c784d22c..6e81f79b1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeName/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeName/index.tsx @@ -1,5 +1,4 @@ -import InputComponent from "@/components/inputComponent"; -import { BuildStatus } from "@/constants/enums"; +import { Input } from "@/components/ui/input"; import useFlowsManagerStore from "@/stores/flowsManagerStore"; import useFlowStore from "@/stores/flowStore"; import { VertexBuildTypeAPI } from "@/types/api"; @@ -39,7 +38,7 @@ export default function NodeName({ return inputName ? (
- { setInputName(false); if (nodeName?.trim() !== "") { @@ -60,10 +59,8 @@ export default function NodeName({ }} value={nodeName} autoFocus - onChange={setNodeName} - password={false} - blurOnEnter={true} - id={`input-title-${display_name}`} + onChange={(e) => setNodeName(e.target.value)} + data-testid={`input-title-${display_name}`} />
) : ( diff --git a/src/frontend/src/CustomNodes/GenericNode/components/handleRenderComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/handleRenderComponent/index.tsx index b821098ab..1492d0ee0 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/handleRenderComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/handleRenderComponent/index.tsx @@ -1,14 +1,13 @@ import { useDarkStore } from "@/stores/darkStore"; import useFlowStore from "@/stores/flowStore"; -import { log } from "console"; import { useEffect, useMemo, useRef, useState } from "react"; -import { Handle, Position, useViewport } from "reactflow"; +import { Handle, Position } from "reactflow"; import ShadTooltip from "../../../../components/shadTooltipComponent"; import { isValidConnection, scapedJSONStringfy, } from "../../../../utils/reactflowUtils"; -import { classNames, cn, groupByFamily } from "../../../../utils/utils"; +import { cn, groupByFamily } from "../../../../utils/utils"; import HandleTooltipComponent from "../HandleTooltipComponent"; export default function HandleRenderComponent({ @@ -42,7 +41,7 @@ export default function HandleRenderComponent({ nodeId: string; colorName?: string[]; }) { - const handleColorName = colorName?.[0]; + const handleColorName = colorName?.[0] ?? ""; const innerColorName = `inner-${handleColorName}`; const innerForegroundColorName = `${innerColorName}-foreground`; @@ -156,7 +155,7 @@ export default function HandleRenderComponent({ source: undefined, sourceHandle: undefined, type: tooltipTitle, - color: colors[0], + color: handleColorName, } : { sourceHandle: myId, @@ -164,7 +163,7 @@ export default function HandleRenderComponent({ target: undefined, targetHandle: undefined, type: tooltipTitle, - color: colors[0], + color: handleColorName, }, [left, myId, nodeId, tooltipTitle, colors], ); diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index b079364b5..fbe432d28 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -5,15 +5,12 @@ import { usePostValidateComponentCode } from "@/controllers/API/queries/nodes/us import { useEffect, useMemo, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; -import IconComponent, { - ForwardedIconComponent, -} from "../../components/genericIconComponent"; +import { ForwardedIconComponent } from "../../components/genericIconComponent"; import ShadTooltip from "../../components/shadTooltipComponent"; import { Button } from "../../components/ui/button"; import { TOOLTIP_HIDDEN_OUTPUTS, TOOLTIP_OPEN_HIDDEN_OUTPUTS, - TOOLTIP_OUTDATED_NODE, } from "../../constants/constants"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import useAlertStore from "../../stores/alertStore"; @@ -379,6 +376,7 @@ export default function GenericNode({
diff --git a/src/frontend/src/CustomNodes/NoteNode/NoteToolbarComponent/index.tsx b/src/frontend/src/CustomNodes/NoteNode/NoteToolbarComponent/index.tsx index 4797e7997..62e2077e1 100644 --- a/src/frontend/src/CustomNodes/NoteNode/NoteToolbarComponent/index.tsx +++ b/src/frontend/src/CustomNodes/NoteNode/NoteToolbarComponent/index.tsx @@ -17,10 +17,9 @@ import useAlertStore from "@/stores/alertStore"; import useFlowStore from "@/stores/flowStore"; import useFlowsManagerStore from "@/stores/flowsManagerStore"; import { useShortcutsStore } from "@/stores/shortcuts"; -import { NodeDataType, noteDataType } from "@/types/flow"; +import { noteDataType } from "@/types/flow"; import { classNames, cn, openInNewTab } from "@/utils/utils"; -import { cloneDeep, set, take } from "lodash"; -import { useState } from "react"; +import { cloneDeep } from "lodash"; import IconComponent from "../../../components/genericIconComponent"; export default function NoteToolbarComponent({ @@ -30,7 +29,6 @@ export default function NoteToolbarComponent({ data: noteDataType; bgColor: string; }) { - const setSuccessData = useAlertStore((state) => state.setSuccessData); const setNoticeData = useAlertStore((state) => state.setNoticeData); const nodes = useFlowStore((state) => state.nodes); const setLastCopiedSelection = useFlowStore( @@ -95,9 +93,12 @@ export default function NoteToolbarComponent({ >
@@ -131,9 +132,10 @@ export default function NoteToolbarComponent({ className={cn( "h-4 w-4 rounded-full hover:border hover:border-ring", bgColor === color ? "border-2 border-blue-500" : "", + code === null && "border", )} style={{ - backgroundColor: code, + backgroundColor: code ?? "#00000000", }} > diff --git a/src/frontend/src/CustomNodes/NoteNode/index.tsx b/src/frontend/src/CustomNodes/NoteNode/index.tsx index b57cd1c7f..0e39ebf64 100644 --- a/src/frontend/src/CustomNodes/NoteNode/index.tsx +++ b/src/frontend/src/CustomNodes/NoteNode/index.tsx @@ -19,7 +19,9 @@ function NoteNode({ selected: boolean; }) { const bgColor = - data.node?.template.backgroundColor ?? Object.keys(COLOR_OPTIONS)[0]; + Object.keys(COLOR_OPTIONS).find( + (key) => key === data.node?.template.backgroundColor, + ) ?? Object.keys(COLOR_OPTIONS)[0]; const nodeDiv = useRef(null); const [size, setSize] = useState({ width: 0, height: 0 }); //tricky to start the description with the right size @@ -61,12 +63,13 @@ function NoteNode({ maxWidth: NOTE_NODE_MAX_WIDTH, minWidth: NOTE_NODE_MIN_WIDTH, minHeight: NOTE_NODE_MIN_HEIGHT, - backgroundColor: COLOR_OPTIONS[bgColor], + backgroundColor: COLOR_OPTIONS[bgColor] ?? "#00000000", }} ref={nodeDiv} className={cn( - "flex h-full w-full flex-col gap-3 border border-b p-3 transition-all", - selected ? "" : "-z-50 shadow-sm", + "flex h-full w-full flex-col gap-3 rounded-xl p-3 transition-all", + COLOR_OPTIONS[bgColor] !== null && + `border ${!selected && "-z-50 shadow-sm"}`, )} >
diff --git a/src/frontend/src/components/inputComponent/components/popover/index.tsx b/src/frontend/src/components/inputComponent/components/popover/index.tsx index dba252c9a..64b67f143 100644 --- a/src/frontend/src/components/inputComponent/components/popover/index.tsx +++ b/src/frontend/src/components/inputComponent/components/popover/index.tsx @@ -15,7 +15,7 @@ import { import { cn } from "@/utils/utils"; import { PopoverAnchor } from "@radix-ui/react-popover"; import { X } from "lucide-react"; -import React, { useState } from "react"; +import { useState } from "react"; const CustomInputPopover = ({ id, @@ -97,11 +97,10 @@ const CustomInputPopover = ({ )) ) : selectedOption?.length > 0 ? (
{selectedOption}
diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index 56428c395..fff408ba6 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -40,11 +40,9 @@ export default function TableAutoCellRender({ else if (value === "success") { return ( {value} @@ -52,11 +50,9 @@ export default function TableAutoCellRender({ } else if (value === "failure") { return ( {value} diff --git a/src/frontend/src/components/ui/badge.tsx b/src/frontend/src/components/ui/badge.tsx index 50f88f458..86a997d9e 100644 --- a/src/frontend/src/components/ui/badge.tsx +++ b/src/frontend/src/components/ui/badge.tsx @@ -15,15 +15,20 @@ const badgeVariants = cva( destructive: "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground", outline: "text-primary/80 border-ring/60", - secondaryStatic: "bg-input text-muted-foreground border-0", + secondaryStatic: "bg-muted text-muted-foreground border-0", pinkStatic: "bg-accent-pink text-accent-pink-foreground border-0", + emerald: + "bg-accent-emerald text-accent-emerald-foreground hover:bg-accent-emerald-hover", + successStatic: + "bg-accent-emerald text-accent-emerald-foreground border-0", + errorStatic: "bg-error-background text-error-foreground border-0", }, size: { sm: "h-4 text-xs", md: "h-5 text-sm", lg: "h-6 text-base", sq: "h-6 px-1.5 text-sm font-medium rounded-md", - xq: "h-5 px-1 text-xs font-medium rounded-md", + xq: "h-6 px-1.5 text-xs font-medium rounded-sm", }, }, defaultVariants: { diff --git a/src/frontend/src/components/ui/dialog-with-no-close.tsx b/src/frontend/src/components/ui/dialog-with-no-close.tsx index 3c025bfd8..07553b0c2 100644 --- a/src/frontend/src/components/ui/dialog-with-no-close.tsx +++ b/src/frontend/src/components/ui/dialog-with-no-close.tsx @@ -25,7 +25,7 @@ const DialogOverlay = React.forwardRef< (({ className, ...props }, ref) => ( {autoSave ? ( -
+
Saving your changes...
diff --git a/src/frontend/src/modals/templatesModal/components/navComponent/index.tsx b/src/frontend/src/modals/templatesModal/components/navComponent/index.tsx index 17d8b2366..7c4ad14b3 100644 --- a/src/frontend/src/modals/templatesModal/components/navComponent/index.tsx +++ b/src/frontend/src/modals/templatesModal/components/navComponent/index.tsx @@ -65,7 +65,7 @@ export function Nav({ categories, currentTab, setCurrentTab }: NavProps) { name={link.icon} className={`h-4 w-4 stroke-2 ${ currentTab === link.id - ? "x-gradient" + ? "text-accent-pink-foreground" : "text-muted-foreground" }`} /> diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 75c5cb075..879d29bc7 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -8,9 +8,9 @@ import ForwardedIconComponent from "@/components/genericIconComponent"; import LoadingComponent from "@/components/loadingComponent"; import { SidebarTrigger, useSidebar } from "@/components/ui/sidebar"; import { + COLOR_OPTIONS, NOTE_NODE_MIN_HEIGHT, NOTE_NODE_MIN_WIDTH, - SHADOW_COLOR_OPTIONS, } from "@/constants/constants"; import { useGetBuildsQuery } from "@/controllers/API/queries/_builds"; import { track } from "@/customization/utils/analytics"; @@ -196,8 +196,7 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { const zoomLevel = reactFlowInstance?.getZoom(); const shadowBoxWidth = NOTE_NODE_MIN_WIDTH * (zoomLevel || 1); const shadowBoxHeight = NOTE_NODE_MIN_HEIGHT * (zoomLevel || 1); - const shadowBoxBackgroundColor = - SHADOW_COLOR_OPTIONS[Object.keys(SHADOW_COLOR_OPTIONS)[0]]; + const shadowBoxBackgroundColor = COLOR_OPTIONS[Object.keys(COLOR_OPTIONS)[0]]; function handleGroupNode() { takeSnapshot(); @@ -432,6 +431,11 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { const onDrop = useCallback( (event: React.DragEvent) => { event.preventDefault(); + const grabbingElement = + document.getElementsByClassName("cursor-grabbing"); + if (grabbingElement.length > 0) { + document.body.removeChild(grabbingElement[0]); + } if (event.dataTransfer.types.some((type) => isSupportedNodeTypes(type))) { takeSnapshot(); @@ -561,20 +565,6 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { [isAddingNote, setNodes, reactFlowInstance, getNodeId, setFilterEdge], ); - const onPaneMouseMove = useCallback( - (event: React.MouseEvent) => { - if (isAddingNote) { - const shadowBox = document.getElementById("shadow-box"); - if (shadowBox) { - shadowBox.style.display = "block"; - shadowBox.style.left = `${event.clientX - shadowBoxWidth / 2}px`; - shadowBox.style.top = `${event.clientY - shadowBoxHeight / 2}px`; - } - } - }, - [isAddingNote], - ); - const handleEdgeClick = (event, edge) => { const color = nodeColorsName[edge?.data?.targetHandle?.inputTypes[0]] || @@ -588,6 +578,25 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { const { open } = useSidebar(); + useEffect(() => { + const handleGlobalMouseMove = (event) => { + if (isAddingNote) { + const shadowBox = document.getElementById("shadow-box"); + if (shadowBox) { + shadowBox.style.display = "block"; + shadowBox.style.left = `${event.clientX - shadowBoxWidth / 2}px`; + shadowBox.style.top = `${event.clientY - shadowBoxHeight / 2}px`; + } + } + }; + + document.addEventListener("mousemove", handleGlobalMouseMove); + + return () => { + document.removeEventListener("mousemove", handleGlobalMouseMove); + }; + }, [isAddingNote, shadowBoxWidth, shadowBoxHeight]); + return (
{showCanvas ? ( @@ -625,10 +634,9 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { panActivationKeyCode={""} proOptions={{ hideAttribution: true }} onPaneClick={onPaneClick} - onPaneMouseMove={onPaneMouseMove} onEdgeClick={handleEdgeClick} > - + {!view && ( <> @@ -637,6 +645,12 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { tooltipText="Add Note" onClick={() => { setIsAddingNote(true); + const shadowBox = document.getElementById("shadow-box"); + if (shadowBox) { + shadowBox.style.display = "block"; + shadowBox.style.left = `${position.current.x - shadowBoxWidth / 2}px`; + shadowBox.style.top = `${position.current.y - shadowBoxHeight / 2}px`; + } }} iconClasses="text-primary" testId="add_note" @@ -678,6 +692,7 @@ export default function Page({ view }: { view?: boolean }): JSX.Element { width: `${shadowBoxWidth}px`, height: `${shadowBoxHeight}px`, backgroundColor: `${shadowBoxBackgroundColor}`, + opacity: 0.7, pointerEvents: "none", }} >
diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sidebarFilterComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sidebarFilterComponent/index.tsx index 66b8bb5ed..4b0bb3c55 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sidebarFilterComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sidebarFilterComponent/index.tsx @@ -5,18 +5,25 @@ import { Button } from "@/components/ui/button"; export function SidebarFilterComponent({ isInput, type, + color, resetFilters, }: { isInput: boolean; type: string; + color: string; resetFilters: () => void; }) { return ( -
+
{isInput ? "Input" : "Output"}:{" "} diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx index ce74d1a7a..da415e5e7 100644 --- a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx @@ -37,6 +37,8 @@ export const SidebarDraggableComponent = forwardRef( official, beta, legacy, + disabled, + disabledTooltip, }: { sectionName: string; apiClass: APIClassType; @@ -49,6 +51,8 @@ export const SidebarDraggableComponent = forwardRef( official: boolean; beta: boolean; legacy: boolean; + disabled?: boolean; + disabledTooltip?: string; }, ref, ) => { @@ -103,116 +107,129 @@ export const SidebarDraggableComponent = forwardRef( open={open} key={itemName} > -
{ - e.preventDefault(); - setOpen(true); - }} - key={itemName} - data-tooltip-id={itemName} - tabIndex={0} - onKeyDown={handleKeyDown} - className="rounded-md outline-none ring-ring focus-visible:ring-2" +
{ - document.body.removeChild( - document.getElementsByClassName("cursor-grabbing")[0], - ); + onPointerDown={handlePointerDown} + onContextMenuCapture={(e) => { + e.preventDefault(); + setOpen(true); }} + key={itemName} + data-tooltip-id={itemName} + tabIndex={0} + onKeyDown={handleKeyDown} + className="rounded-md outline-none ring-ring focus-visible:ring-2" > - -
- - - {display_name} - - - {beta && ( - - BETA - +
- LEGACY - - )} -
-
- -
- - - - -
- {" "} - Download{" "} -
{" "} -
- {!official && ( - + draggable={!error} + style={{ + borderLeftColor: color, + }} + onDragStart={onDragStart} + onDragEnd={() => { + document.body.removeChild( + document.getElementsByClassName("cursor-grabbing")[0], + ); + }} + > + +
+ + + {display_name} + + + {beta && ( + + BETA + + )} + {legacy && ( + + LEGACY + + )} +
+
+ {!disabled && ( + + )} +
+ + + +
{" "} - Delete{" "} + Download{" "}
{" "}
- )} -
+ {!official && ( + +
+ {" "} + Delete{" "} +
{" "} +
+ )} + +
-
+ ); }, diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx index 73fa4d4b1..39f0e4912 100644 --- a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx @@ -30,6 +30,7 @@ import { Switch } from "@/components/ui/switch"; import { CustomLink } from "@/customization/components/custom-link"; import { useAddComponent } from "@/hooks/useAddComponent"; import { useStoreStore } from "@/stores/storeStore"; +import { checkChatInput } from "@/utils/reactflowUtils"; import { nodeColors, SIDEBAR_BUNDLES, @@ -97,6 +98,7 @@ export function FlowSidebarComponent() { (category) => Object.keys(category).length > 0, ); }, [dataFilter]); + const [sortedCategories, setSortedCategories] = useState([]); useEffect(() => { filterComponents(); @@ -128,6 +130,7 @@ export function FlowSidebarComponent() { // Apply search filter if (search && fuse) { const results = fuse.search(search); + setSortedCategories(results.map((result) => result.item.category)); filteredData = Object.fromEntries( Object.entries(data).map(([category, items]) => { const categoryResults = results.filter( @@ -303,12 +306,21 @@ export function FlowSidebarComponent() { dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0, ); + const hasCategoryItems = categories.some( + (item) => + dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0, + ); + function handleClearSearch() { setSearch(""); setFilterData(data); setOpenCategories([]); } + const nodes = useFlowStore((state) => state.nodes); + + const chatInputAdded = checkChatInput(nodes); + return ( @@ -339,12 +351,11 @@ export function FlowSidebarComponent() {
- - Show{" "} - + + Show + BETA - {" "} - Components +
- - Show{" "} - + + Show + LEGACY - {" "} - Components +
- {" "} - to search components +
)}
@@ -402,6 +411,7 @@ export function FlowSidebarComponent() { { setFilterEdge([]); setFilterData(data); @@ -409,19 +419,186 @@ export function FlowSidebarComponent() { /> )} - + {hasResults ? ( <> - - - - {!data - ? Array.from({ length: 5 }).map((_, index) => ( - - - - )) - : categories.map( + {hasCategoryItems && ( + + + + {!data + ? Array.from({ length: 5 }).map((_, index) => ( + + + + )) + : categories + .toSorted( + (a, b) => + (search !== "" + ? sortedCategories + : categories + ).findIndex((value) => value === a.name) - + (search !== "" + ? sortedCategories + : categories + ).findIndex((value) => value === b.name), + ) + .map( + (item) => + dataFilter[item.name] && + Object.keys(dataFilter[item.name]).length > 0 && ( + { + setOpenCategories((prev) => + isOpen + ? [...prev, item.name] + : prev.filter( + (cat) => cat !== item.name, + ), + ); + }} + > + + + +
+ handleKeyDown(e, item.name) + } + className="flex cursor-pointer items-center gap-2" + > + + + {item.display_name} + + +
+
+
+ +
+ {Object.keys(dataFilter[item.name]) + .sort((a, b) => + sensitiveSort( + dataFilter[item.name][a] + .display_name, + dataFilter[item.name][b] + .display_name, + ), + ) + .map((SBItemName: string, idx) => ( + + + onDragStart(event, { + type: removeCountFromString( + SBItemName, + ), + node: dataFilter[item.name][ + SBItemName + ], + }) + } + color={nodeColors[item.name]} + itemName={SBItemName} + error={ + !!dataFilter[item.name][ + SBItemName + ].error + } + display_name={ + dataFilter[item.name][ + SBItemName + ].display_name + } + official={ + dataFilter[item.name][ + SBItemName + ].official === false + ? false + : true + } + beta={ + dataFilter[item.name][ + SBItemName + ].beta ?? false + } + legacy={ + dataFilter[item.name][ + SBItemName + ].legacy ?? false + } + disabled={ + SBItemName === "ChatInput" && + chatInputAdded + } + disabledTooltip="Chat input already added" + /> + + ))} +
+
+
+
+ ), + )} +
+
+
+ )} + {hasBundleItems && ( + + Bundles + + + {bundles + .toSorted( + (a, b) => + (search !== "" + ? sortedCategories + : bundles + ).findIndex((value) => value === a.name) - + (search !== "" + ? sortedCategories + : bundles + ).findIndex((value) => value === b.name), + ) + .map( (item) => dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0 && ( @@ -440,7 +617,6 @@ export function FlowSidebarComponent() {
handleKeyDown(e, item.name) @@ -449,14 +625,14 @@ export function FlowSidebarComponent() { > - + {item.display_name}
@@ -526,6 +702,11 @@ export function FlowSidebarComponent() { dataFilter[item.name][SBItemName] .legacy ?? false } + disabled={ + SBItemName === "ChatInput" && + chatInputAdded + } + disabledTooltip="Chat input already added" /> ))} @@ -535,126 +716,6 @@ export function FlowSidebarComponent() { ), )} -
-
-
- {hasBundleItems && ( - - Bundles - - - {bundles.map( - (item) => - dataFilter[item.name] && - Object.keys(dataFilter[item.name]).length > 0 && ( - { - setOpenCategories((prev) => - isOpen - ? [...prev, item.name] - : prev.filter((cat) => cat !== item.name), - ); - }} - > - - - -
- handleKeyDown(e, item.name) - } - className="flex cursor-pointer items-center gap-2" - > - - - {item.display_name} - - -
-
-
- -
- {Object.keys(dataFilter[item.name]) - .sort((a, b) => - sensitiveSort( - dataFilter[item.name][a].display_name, - dataFilter[item.name][b].display_name, - ), - ) - .map((SBItemName: string, idx) => ( - - - onDragStart(event, { - type: removeCountFromString( - SBItemName, - ), - node: dataFilter[item.name][ - SBItemName - ], - }) - } - color={nodeColors[item.name]} - itemName={SBItemName} - error={ - !!dataFilter[item.name][SBItemName] - .error - } - display_name={ - dataFilter[item.name][SBItemName] - .display_name - } - official={ - dataFilter[item.name][SBItemName] - .official === false - ? false - : true - } - beta={ - dataFilter[item.name][SBItemName] - .beta ?? false - } - legacy={ - dataFilter[item.name][SBItemName] - .legacy ?? false - } - /> - - ))} -
-
-
-
- ), - )}
diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/shortcutDisplay/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/shortcutDisplay/index.tsx index 6aa211e17..24860b26c 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/shortcutDisplay/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/shortcutDisplay/index.tsx @@ -18,7 +18,7 @@ export default function ShortcutDisplay({ {name && {name} } diff --git a/src/frontend/src/pages/FlowPage/index.tsx b/src/frontend/src/pages/FlowPage/index.tsx index 0a9ca801b..a3773a6a4 100644 --- a/src/frontend/src/pages/FlowPage/index.tsx +++ b/src/frontend/src/pages/FlowPage/index.tsx @@ -167,7 +167,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
{currentFlow && (
- + {!view && }
diff --git a/src/frontend/src/style/classes.css b/src/frontend/src/style/classes.css index f617defb7..25500fbee 100644 --- a/src/frontend/src/style/classes.css +++ b/src/frontend/src/style/classes.css @@ -273,11 +273,21 @@ pre { } [type="search"]:not(:placeholder-shown)::-webkit-search-cancel-button { - -webkit-appearance: none; - background-color: hsl(var(--primary)); opacity: 1 !important; - -webkit-mask-image: url("data:image/svg+xml;utf8,"); - background-size: 20px 20px; - height: 20px; - width: 20px; +} + +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; + height: 16px; + width: 16px; + margin-left: 0.4em; + position: relative; + right: -4px; + mask-image: url("data:image/svg+xml;utf8,"); + background-color: hsl(var(--foreground)) !important; + background-image: none; + cursor: pointer; +} +.react-flow__background pattern circle { + fill: hsl(var(--canvas-dot)) !important; } diff --git a/src/frontend/src/style/index.css b/src/frontend/src/style/index.css index 41312c506..4c6cb0924 100644 --- a/src/frontend/src/style/index.css +++ b/src/frontend/src/style/index.css @@ -32,18 +32,17 @@ --secondary-hover: 240 6% 90%; /* hsl(240, 6%, 90%) */ --placeholder-foreground: 240 5% 65%; /* hsl(240, 5%, 65%) */ --canvas: 240 5% 96%; /* hsl(240, 5%, 96%) */ + --canvas-dot: 240 5% 65%; /* hsl(240, 5%, 65%) */ --accent-emerald: 149 80% 90%; /* hsl(149, 80%, 90%) */ --accent-emerald-foreground: 161 41% 30%; /* hsl(161, 41%, 30%) */ + --accent-emerald-hover: 152.4 76% 80.4%; /* hsl(152.4, 76%, 80.4%) */ --accent-indigo: 226 100% 94%; /* hsl(226, 100%, 94%) */ --accent-indigo-foreground: 243 75% 59%; /* hsl(243, 75%, 59%) */ --accent-pink: 326 78% 95%; /* hsl(326, 78%, 95%) */ --accent-pink-foreground: 333 71% 51%; /* hsl(333, 71%, 51%) */ - --note-amber: 48 97% 77%; /* hsl(48, 97%, 77%) */ --tooltip: 0 0% 0%; /* hsl(0, 0%, 0%) */ --tooltip-foreground: 0 0% 100%; /* hsl(0, 0%, 100%) */ - --canvas-dark: 240 6% 10%; /* hsl(240, 6%, 10%) */ - --node-selected: 243 75% 59%; --round-btn-shadow: #00000063; --ice: #31a3cc; @@ -89,28 +88,22 @@ --status-blue: #2563eb; --status-gray: #6b7280; --connection: #555; - --note-default: #f1f5f9; - --note-indigo: #e0e7ff; - --note-emerald: #d1fae5; - --note-red: #fee2e2; + + --note-amber: 48 96.6% 76.7%; /* hsl(48, 96.6%, 76.7%) */ + --note-neutral: 240 5.9% 90%; /* hsl(240, 5.9%, 90%) */ + --note-rose: 352.7 96.1% 90%; /* hsl(352.7, 96.1%, 90%) */ + --note-blue: 213.3 96.9% 87.3%; /* hsl(213.3, 96.9%, 87.3%) */ + --note-lime: 80.9 88.5% 79.6%; /* hsl(80.9, 88.5%, 79.6%) */ + --error-red: 0, 86%, 97%; /*hsla(0, 86%, 97%)*/ --error-red-border: 0, 96%, 89%; /*hsla(0,96%,89%)*/ - --note-default-opacity: #f1f5f980; - --note-indigo-opacity: #312e8180; - --note-emerald-opacity: #064e3b80; - --note-amber-opacity: #78350f80; - --note-red-opacity: #7f1d1d80; + --code-background: var(--canvas); - --emerald-success: 160.1 84.1% 39.4%; - --accent-emerald-foreground: 161.4 93.5% 30.4%; --placeholder: 240 5% 64.9%; --hard-zinc: 240 5.2% 33.9%; --smooth-red: 0 93.3% 94.1%; --radius: 0.5rem; - --accent-pink: 327.3 73.3% 97.1%; - --accent-pink-foreground: 333.3 71.4% 50.6%; - --inner-yellow: 40.6 96.1% 40.4%; --inner-yellow-foreground: 50.4 97.8% 63.5%; --inner-yellow-muted-foreground: 35.5 91.7% 32.9%; @@ -180,30 +173,25 @@ --secondary-hover: 240 4% 16%; /* hsl(240, 4%, 16%) */ --placeholder-foreground: 240 4% 46%; /* hsl(240, 4%, 46%) */ --canvas: 0 0% 0%; /* hsl(0, 0%, 0%) */ + --canvas-dot: 240 5% 34%; /* hsl(240, 5%, 34%) */ --accent-emerald: 164 86% 16%; /* hsl(164, 86%, 16%) */ --accent-emerald-foreground: 158 64% 52%; /* hsl(158, 64%, 52%) */ + --accent-emerald-hover: 163.1 88.1% 19.8%; /* hsl(163.1, 88.1%, 19.8%) */ --accent-indigo: 242 25% 34%; /* hsl(242, 25%, 34%) */ --accent-indigo-foreground: 234 89% 74%; /* hsl(234, 89%, 74%) */ - --accent-pink: 336 30% 30%; /* hsl(336, 30%, 30%) */ + --accent-pink: 336 69% 30%; /* hsl(336, 69%, 30%) */ --accent-pink-foreground: 329 86% 70%; /* hsl(329, 86%, 70%) */ - --note-amber: 46 97% 65%; /* hsl(46, 97%, 65%) */ --tooltip: 0 0% 100%; /* hsl(0, 0%, 100%) */ --tooltip-foreground: 0 0% 0%; /* hsl(0, 0%, 0%) */ --error-red: 0, 75%, 15%; /*hsla(0, 75%, 15%)*/ --error-red-border: 0, 70%, 35%; /*hsla(0,70%,35%)*/ - --note-default: #0f172a; - --note-indigo: #312e81; - --note-emerald: #064e3b; - --note-red: #7f1d1d; - --note-placeholder: 216 12% 84%; /* hsl(216 12% 84%) */ - - --note-default-opacity: #0f172a80; - --note-indigo-opacity: #312e8180; - --note-emerald-opacity: #064e3b80; - --note-amber-opacity: #78350f80; - --note-red-opacity: #7f1d1d80; + --note-amber: 45.9 96.7% 64.5%; /* hsl(45.9, 96.7%, 64.5%) */ + --note-neutral: 240 4.9% 83.9%; /* hsl(240, 4.9%, 83.9%) */ + --note-rose: 352.6 95.7% 81.8%; /* hsl(352.6, 95.7%, 81.8%) */ + --note-blue: 211.7 96.4% 78.4%; /* hsl(211.7, 96.4%, 78.4%) */ + --note-lime: 82 84.5% 67.1%; /* hsl(82, 84.5%, 67.1%) */ --node-selected: 234 89% 74%; @@ -234,8 +222,6 @@ --component-icon: #c35f85; --flow-icon: #2467e4; - /* Colors that are shared in dark and light mode */ - --blur-shared: #151923d2; --build-trigger: #dc735b; --chat-trigger: #5c8be1; --chat-trigger-disabled: #2d3b54; @@ -262,14 +248,10 @@ --sidebar-accent-foreground: 240 4.8% 95.9%; --sidebar-border: 240 3.7% 15.9%; --sidebar-ring: 217.2 91.2% 59.8%; - --emerald-success: 160.1 84.1% 39.4%; --placeholder: 240 5% 64.9%; --hard-zinc: 240 5.2% 33.9%; --smooth-red: 0 93.3% 94.1%; - --accent-pink: 335.9 69% 30.4%; - --accent-pink-foreground: 330.4 81.2% 60.4%; - --inner-yellow: 47.9 95.8% 53.1%; --inner-yellow-foreground: 35.5 91.7% 32.9%; --inner-yellow-muted-foreground: 50.4 97.8% 63.5%; diff --git a/src/frontend/tailwind.config.mjs b/src/frontend/tailwind.config.mjs index de91d7425..c33fd29ef 100644 --- a/src/frontend/tailwind.config.mjs +++ b/src/frontend/tailwind.config.mjs @@ -69,11 +69,9 @@ const config = { "build-trigger": "var(--build-trigger)", "chat-trigger": "var(--chat-trigger)", "chat-trigger-disabled": "var(--chat-trigger-disabled)", - "blur-shared": "var(--blur-shared)", "dark-blue": "var(--dark-blue)", "dark-gray": "var(--dark-gray)", "dark-red": "var(--dark-red)", - "note-placeholder": "var(--note-placeholder)", error: { DEFAULT: "var(--error)", background: "var(--error-background)", @@ -97,7 +95,11 @@ const config = { "medium-high-indigo": "var(--medium-high-indigo)", "medium-indigo": "var(--medium-indigo)", "medium-low-gray": "var(--medium-low-gray)", - "note-amber": "var(--note-amber)", + "note-amber": "hsl(var(--note-amber))", + "note-neutral": "hsl(var(--note-neutral))", + "note-rose": "hsl(var(--note-rose))", + "note-blue": "hsl(var(--note-blue))", + "note-lime": "hsl(var(--note-lime))", "status-green": "var(--status-green)", "status-red": "var(--status-red)", "status-yellow": "var(--status-yellow)", @@ -120,7 +122,7 @@ const config = { "code-background": "hsl(var(--code-background))", canvas: { DEFAULT: "hsl(var(--canvas))", - dark: "hsl(var(--canvas-dark))", + dot: "hsl(var(--canvas-dot))", }, ice: "var(--ice)", selected: "var(--selected)", @@ -128,13 +130,15 @@ const config = { border: "hsl(var(--border))", input: "hsl(var(--input))", ring: "hsl(var(--ring))", - "error-red":"hsl(var(--error-red))", - "error-red-border":"hsl(var(--error-red-border))", + "error-red": "hsl(var(--error-red))", + "error-red-border": "hsl(var(--error-red-border))", "node-selected": "hsl(var(--node-selected))", background: "hsl(var(--background))", foreground: "hsl(var(--foreground))", - "emerald-success": "hsl(var(--emerald-success))", - "accent-emerald-foreground": "hsl(var(--accent-emerald-foreground))", + "accent-emerald": { + DEFAULT: "hsl(var(--accent-emerald))", + foreground: "hsl(var(--accent-emerald-foreground))", + }, "emerald-smooth": "hsl(var(--emaral-smooth))", "emerald-hard": "hsl(var(--emeral-hard))", placeholder: "hsl(var(--placeholder))", @@ -166,6 +170,7 @@ const config = { "accent-emerald": { DEFAULT: "hsl(var(--accent-emerald))", foreground: "hsl(var(--accent-emerald-foreground))", + hover: "hsl(var(--accent-emerald-hover))", }, "accent-indigo": { DEFAULT: "hsl(var(--accent-indigo))", @@ -377,34 +382,34 @@ const config = { tailwindcssTypography, tailwindcssDottedBackground, plugin(function ({ addUtilities, theme, e }) { - const colors = theme('colors'); + const colors = theme("colors"); - const generateUtilities = (colors, prefix = '') => { + const generateUtilities = (colors, prefix = "") => { return Object.keys(colors).reduce((acc, colorName) => { const colorValue = colors[colorName]; const className = prefix ? `${prefix}-${e(colorName)}` : e(colorName); - if (typeof colorValue === 'string') { + if (typeof colorValue === "string") { acc[`.truncate-${className}`] = { - position: 'relative', - overflow: 'hidden', - '&::after': { + position: "relative", + overflow: "hidden", + "&::after": { content: '""', - position: 'absolute', - inset: '0 0 0 0', + position: "absolute", + inset: "0 0 0 0", background: `linear-gradient(to right, transparent, 75%, ${colorValue})`, }, }; - } else if (typeof colorValue === 'object') { + } else if (typeof colorValue === "object") { // Use the DEFAULT value for the base class if it exists if (colorValue.DEFAULT) { acc[`.truncate-${className}`] = { - position: 'relative', - overflow: 'hidden', - '&::after': { + position: "relative", + overflow: "hidden", + "&::after": { content: '""', - position: 'absolute', - inset: '0 0 0 0', + position: "absolute", + inset: "0 0 0 0", background: `linear-gradient(to right, transparent, ${colorValue.DEFAULT})`, }, }; @@ -419,7 +424,7 @@ const config = { const newUtilities = generateUtilities(colors); - addUtilities(newUtilities, ['responsive', 'hover']); + addUtilities(newUtilities, ["responsive", "hover"]); }), plugin(({ addVariant }) => { addVariant("group-increment-hover", ":merge(.group-increment):hover &"); diff --git a/src/frontend/tests/core/features/group.spec.ts b/src/frontend/tests/core/features/group.spec.ts index 5cfdb4ec7..04217fee4 100644 --- a/src/frontend/tests/core/features/group.spec.ts +++ b/src/frontend/tests/core/features/group.spec.ts @@ -35,10 +35,7 @@ test.describe("group node test", () => { await page.getByRole("button", { name: "Group" }).click(); await page.getByTestId("title-Group").dblclick(); - await page - .getByTestId("popover-anchor-input-title-Group") - .first() - .fill("test"); + await page.getByTestId("input-title-Group").first().fill("test"); await page.getByTestId("icon-Ungroup").first().click(); await page.keyboard.press("Control+g"); await page.getByTestId("title-OpenAI").isVisible(); diff --git a/src/frontend/tests/extended/features/sticky-notes.spec.ts b/src/frontend/tests/extended/features/sticky-notes.spec.ts index e4b3c8430..9baa9de31 100644 --- a/src/frontend/tests/extended/features/sticky-notes.spec.ts +++ b/src/frontend/tests/extended/features/sticky-notes.spec.ts @@ -105,7 +105,10 @@ The future of AI is both exciting and uncertain. As the technology continues to let hasStyles = await element?.evaluate((el) => { const style = window.getComputedStyle(el); - return style.backgroundColor === "rgb(241, 245, 249)"; + return ( + style.backgroundColor === "rgb(252, 211, 77)" || + style.backgroundColor === "rgb(253, 230, 138)" + ); }); expect(hasStyles).toBe(true); @@ -113,7 +116,7 @@ The future of AI is both exciting and uncertain. As the technology continues to await page.getByTestId("color_picker").click(); - await page.getByTestId("color_picker_button_red").click(); + await page.getByTestId("color_picker_button_rose").click(); await page.waitForTimeout(1000); await page.getByTestId("note_node").click(); @@ -122,7 +125,11 @@ The future of AI is both exciting and uncertain. As the technology continues to hasStyles = await element?.evaluate((el) => { const style = window.getComputedStyle(el); - return style.backgroundColor === "rgb(254, 226, 226)"; + + return ( + style.backgroundColor === "rgb(253, 164, 175)" || + style.backgroundColor === "rgb(254, 205, 211)" + ); }); expect(hasStyles).toBe(true);