Skip to content

Commit

Permalink
feature: add flow notes (#3460)
Browse files Browse the repository at this point in the history
* feat: Add NoteDraggableComponent to extraSidebarComponent

This commit adds the NoteDraggableComponent to the extraSidebarComponent in the FlowPage. The NoteDraggableComponent allows users to drag and drop sticky note icons onto the page. When a note is dragged, its data is set as "note" in the dataTransfer object. The note has a default text value of null and a noteColor of "yellow". This component enhances the user experience by providing a convenient way to add notes to the page.

* feat: Add NoteNode component for displaying and editing notes

This commit adds the NoteNode component, which is responsible for displaying and editing notes in the FlowPage. The NoteNode component includes functionality for resizing, selecting, and editing the note text. It enhances the user experience by providing a convenient way to add and manage notes on the page.

* feat: Add NoteNode and NoteDraggableComponent for managing notes in FlowPage

This commit adds the NoteNode component, responsible for displaying and editing notes in the FlowPage. It also introduces the NoteDraggableComponent, allowing users to drag and drop sticky note icons onto the page. These components enhance the user experience by providing a convenient way to add and manage notes on the page.

* feat: Add DRAG_EVENTS_CUSTOM_TYPESS constant for custom drag event types

This commit adds the DRAG_EVENTS_CUSTOM_TYPESS constant to the constants file. It defines custom drag event types for the generic node and note node components. This constant enhances the code by providing a centralized place to manage and reference the custom drag event types.

* feat: Add support functions for custom drag event types

* feat: Add support for custom drag event types in PageComponent

This commit adds support for custom drag event types in the PageComponent of the FlowPage. It imports the necessary functions from the utils file and uses them to check if the dragged data has supported node types. This enhancement improves the drag and drop functionality by allowing only supported node types to be dropped on the page.

* feat: Add NoteDataType for managing note data in FlowPage

* refactor: create new types for noteNode

* feat: Update NoteNode component to use new NoteDataType

The NoteNode component in the NoteNode/index.tsx file has been updated to use the new NoteDataType for managing note data in the FlowPage. This change ensures consistency and improves the codebase.

* node with title and description

* feat: Add "note" alias for StickyNote in nodeIconsLucide

This commit adds the "note" alias for the StickyNote icon in the nodeIconsLucide object in the styleUtils.ts file. This alias allows for more intuitive usage of the StickyNote icon by providing an alternative name. It improves code readability and maintainability.

* refactor: Update NodeDescription component to use emptyPlaceholder prop

The NodeDescription component in the GenericNode/components/NodeDescription/index.tsx file has been updated to use the emptyPlaceholder prop. This change allows for more flexibility in customizing the placeholder text when the description is empty. It improves code reusability and enhances the user experience.

* refactor: Remove unused Textarea import in NoteNode component

* add initial resize to note component

* [autofix.ci] apply automated fixes

* refactor: add code validation functionality on tanstack mutation (#3469)

* Added Validate endpoint

* Added API Code Validate type

* Added post validate code hook

* Used mutation instead of API call to validate code

* Removed validate code api call

* refactor: Update NodeName component to use full width in GenericNode

The NodeName component in the GenericNode module has been updated to use the full width of the parent container. This change ensures that the input field or tooltip for the node name occupies the entire available space, improving the visual consistency and user experience.

* refactor: Update NodeDescription component to use full height in GenericNode

The NodeDescription component in the GenericNode module has been updated to use the full height of the parent container. This change ensures that the description text area occupies the entire available space, improving the visual consistency and user experience.

* refactor: Update NodeDescription component to use full height in GenericNode

* refactor: Update NodeDescription component to use full height in GenericNode

* increase size control on note node

* refactor: Update NoteNode component to use constants for min and max dimensions

The NoteNode component in the CustomNodes module has been updated to use the constants for the minimum and maximum dimensions. This change improves code readability and maintainability by centralizing the values in the constants file. The component now uses the NOTE_NODE_MIN_WIDTH, NOTE_NODE_MIN_HEIGHT, NOTE_NODE_MAX_HEIGHT, and NOTE_NODE_MAX_WIDTH constants for setting the dimensions of the NodeResizer and the inline styles. This ensures consistency across the application and makes it easier to adjust the dimensions in the future.

* fix overflow issue

* refactor: update NoteDraggableComponent

The NoteDraggableComponent in the extraSidebarComponent module has been updated to remove unused code and improve functionality. The code for adding a note has been removed as it is no longer needed. Additionally, the component has been updated to use a new design and layout for better user experience. This refactor improves the overall code cleanliness and removes unnecessary clutter.

* refactor: Update NoteNode component to use constants for min and max dimensions

* update component to accept multiple colors

* update note colors

* update min width

* refactor: Update NodeDescription component to accept additional styling options

The NodeDescription component in the GenericNode module has been updated to accept additional styling options. The component now includes the inputClassName, mdClassName, and style props, allowing for more customization of the input and markdown elements. This refactor improves the flexibility and extensibility of the component, making it easier to adapt to different design requirements.

* fix bug on description size

* [autofix.ci] apply automated fixes

* feat: skip note nodes when building vertices"

add check to skip nodes of type NoteNode when building vertices in the graph
this prevents unnecessary processing of note nodes which are not part of the actual graph logic

* fix: update serialization and improve error handling (#3516)

* feat(utils): add support for V1BaseModel in serialize_field

Add support for V1BaseModel instances in the serialize_field function by
checking for a "to_json" method. If the method is not present, return the
attribute values as a dictionary.

* refactor: Update field serializer function and error handling in build_flow function

* fix: no module named 'psycopg2' (#3526)

* fix: add dependecy to Dockerfile

* fix: revert quick fix

* fix: update poetry.lock

* feat: add compression support to frontend and backend (#3484)

* Added compression lib to frontend

* Added compression handling to backend

* Added compression to body requests on frontend

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* refactor: add code validation functionality on tanstack mutation (#3469)

* Added Validate endpoint

* Added API Code Validate type

* Added post validate code hook

* Used mutation instead of API call to validate code

* Removed validate code api call

* refactor: Update NodeName component to use full width in GenericNode

The NodeName component in the GenericNode module has been updated to use the full width of the parent container. This change ensures that the input field or tooltip for the node name occupies the entire available space, improving the visual consistency and user experience.

* fix imports

* refactor: remove unused import in styleUtils.ts

* refactor: update checkOldNodesOutput to include only generic nodes

The checkOldNodesOutput function in reactflowUtils.ts has been updated to include only generic nodes when checking for nodes without outputs. This change ensures that only nodes of type "genericNode" are considered, improving the accuracy of the check and preventing false positives.

* refactor: improve checkOldNodesOutput to include only generic nodes

* [autofix.ci] apply automated fixes

* 📝 (frontend): Add data-testid attribute to elements for testing purposes in NodeDescription, NoteToolbarComponent, NoteNode, and Textarea components
✨ (frontend): Create end-to-end test for interacting with sticky notes including creating, editing, duplicating, and deleting notes

* ✨ (stop-building.spec.ts): Add a 1-second delay after clicking the stop building button to improve user experience
✨ (sticky-notes.spec.ts): Add a new end-to-end test for interacting with sticky notes on the main page to ensure functionality and user interaction with sticky notes.

* refactor: update NodeName and GenericNode components to improve UI and code readability

* [autofix.ci] apply automated fixes

* chore: Update NodeDescription component to use dark mode placeholder color

* chore: Update sidebar note component icon to use StickyNote instead of SquarePen

* refactor(main.py): remove unused imports and middleware related to GZip to simplify code and improve readability
feat(main.py): add middleware for configuring logger to improve logging functionality and centralize logging configuration

* add center postion in the flow

* chore: Update NoteNode icon to use SquarePen instead of StickyNote

* [autofix.ci] apply automated fixes

* chore: Update API base URL

* [autofix.ci] apply automated fixes

* chore:  add feature flag for MVPs

* code format

* ✨ (NoteNode/index.tsx): Wrap IconComponent in a div with data-testid "note_icon" for better accessibility and testing
✨ (PageComponent/index.tsx): Add data-testid "add_note" to ControlButton for easier testing and identification
🔧 (sticky-notes.spec.ts): Update test selectors to use new data-testid "note_icon" and "add_note" for improved test reliability

* chore: Update types-markdown to version 3.7.0.20240822

* feat: Add lazy loading for images in sticky-notes.spec.ts

* [autofix.ci] apply automated fixes

* update poetry lock

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Refactor feature flag import for ENABLE_MVPS across components and tests

* Add skip marker to unimplemented test in test_graph_state_model.py

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: Gabriel Luiz Freitas Almeida <[email protected]>
Co-authored-by: Ítalo Johnny <[email protected]>
Co-authored-by: cristhianzl <[email protected]>
  • Loading branch information
6 people authored and carlosrcoelho committed Sep 2, 2024
1 parent 1841e6d commit 2fb7ce0
Show file tree
Hide file tree
Showing 34 changed files with 2,071 additions and 1,066 deletions.
2,026 changes: 1,055 additions & 971 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/backend/base/langflow/api/v1/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ async def build_vertices(
build_task = asyncio.create_task(await asyncio.to_thread(_build_vertex, vertex_id, graph))
try:
await build_task
except asyncio.CancelledError:
except asyncio.CancelledError as exc:
logger.exception(exc)
build_task.cancel()
return

Expand Down
4 changes: 3 additions & 1 deletion src/backend/base/langflow/graph/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
)
from langflow.graph.schema import InterfaceComponentTypes, RunOutputs
from langflow.graph.vertex.base import Vertex, VertexStates
from langflow.graph.vertex.schema import NodeData
from langflow.graph.vertex.schema import NodeData, NodeTypeEnum
from langflow.graph.vertex.types import ComponentVertex, InterfaceVertex, StateVertex
from langflow.logging.logger import LogConfig, configure
from langflow.schema import Data
Expand Down Expand Up @@ -1628,6 +1628,8 @@ def _build_vertices(self) -> list["Vertex"]:
"""Builds the vertices of the graph."""
vertices: list["Vertex"] = []
for frontend_data in self._vertices:
if frontend_data.get("type") == NodeTypeEnum.NoteNode:
continue
try:
vertex_instance = self.get_vertex(frontend_data["id"])
except ValueError:
Expand Down
8 changes: 8 additions & 0 deletions src/backend/base/langflow/graph/vertex/schema.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from enum import Enum

from typing_extensions import NotRequired, TypedDict


class NodeTypeEnum(str, Enum):
NoteNode = "noteNode"
GenericNode = "genericNode"


class Position(TypedDict):
x: float
y: float
Expand All @@ -16,3 +23,4 @@ class NodeData(TypedDict):
positionAbsolute: NotRequired[Position]
selected: NotRequired[bool]
parent_node_id: NotRequired[str]
type: NotRequired[NodeTypeEnum]
4 changes: 1 addition & 3 deletions src/backend/base/langflow/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
)
from langflow.interface.types import get_and_cache_all_types_dict
from langflow.interface.utils import setup_llm_caching
from langflow.logging.logger import configure
from langflow.services.deps import get_cache_service, get_settings_service, get_telemetry_service
from langflow.services.plugins.langfuse_plugin import LangfuseInstance
from langflow.services.utils import initialize_services, teardown_services
from langflow.logging.logger import configure

# Ignore Pydantic deprecation warnings from Langchain
warnings.filterwarnings("ignore", category=PydanticDeprecatedSince20)
Expand Down Expand Up @@ -133,8 +133,6 @@ def create_app():
allow_headers=["*"],
)
app.add_middleware(JavaScriptMIMETypeMiddleware)
# ! Deactivating this until we find a better solution
# app.add_middleware(RequestCancelledMiddleware)

@app.middleware("http")
async def flatten_query_string_lists(request: Request, call_next):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def test_graph_state_model_serialization():
assert serialized_state_model["chat_input"]["message"]["text"] == "Test Sender Name"


@pytest.mark.skip(reason="Not implemented yet")
def test_graph_state_model_json_schema():
chat_input = ChatInput(_id="chat_input")
chat_input.set(input_value="Test Sender Name")
Expand Down
7 changes: 7 additions & 0 deletions src/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"moment": "^2.30.1",
"openseadragon": "^4.1.1",
"p-debounce": "^4.0.0",
"pako": "^2.1.0",
"playwright": "^1.44.1",
"react": "^18.3.1",
"react-ace": "^11.0.1",
Expand Down
8 changes: 8 additions & 0 deletions src/frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,11 @@ body {
width: 100%;
height: 100%;
}
.react-flow__resize-control.handle {
width: 0.75rem!important;
height: 0.75rem !important;
background-color: white !important;
border-color: var(--border) !important;
z-index: 1000 !important;
border-radius: 20% !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ export default function NodeDescription({
description,
selected,
nodeId,
emptyPlaceholder = "Double Click to Edit Description",
charLimit,
inputClassName,
mdClassName,
style,
}: {
description?: string;
selected: boolean;
nodeId: string;
emptyPlaceholder?: string;
charLimit?: number;
inputClassName?: string;
mdClassName?: string;
style?: React.CSSProperties;
}) {
const [inputDescription, setInputDescription] = useState(false);
const [nodeDescription, setNodeDescription] = useState(description);
Expand All @@ -31,35 +41,20 @@ export default function NodeDescription({
}, [description]);

return (
<div className="generic-node-desc">
<div
className={cn(
"generic-node-desc",
!inputDescription ? "overflow-auto" : "",
)}
>
{inputDescription ? (
<Textarea
className="nowheel min-h-40"
autoFocus
onBlur={() => {
setInputDescription(false);
setNodeDescription(nodeDescription);
setNode(nodeId, (old) => ({
...old,
data: {
...old.data,
node: {
...old.data.node,
description: nodeDescription,
},
},
}));
}}
value={nodeDescription}
onChange={(e) => setNodeDescription(e.target.value)}
onKeyDown={(e) => {
handleKeyDown(e, nodeDescription, "");
if (
e.key === "Enter" &&
e.shiftKey === false &&
e.ctrlKey === false &&
e.altKey === false
) {
<>
<Textarea
maxLength={charLimit}
className={cn("nowheel h-full", inputClassName)}
autoFocus
style={style}
onBlur={() => {
setInputDescription(false);
setNodeDescription(nodeDescription);
setNode(nodeId, (old) => ({
Expand All @@ -72,13 +67,50 @@ export default function NodeDescription({
},
},
}));
}
}}
/>
}}
value={nodeDescription}
onChange={(e) => setNodeDescription(e.target.value)}
onKeyDown={(e) => {
handleKeyDown(e, nodeDescription, "");
if (
e.key === "Enter" &&
e.shiftKey === false &&
e.ctrlKey === false &&
e.altKey === false
) {
setInputDescription(false);
setNodeDescription(nodeDescription);
setNode(nodeId, (old) => ({
...old,
data: {
...old.data,
node: {
...old.data.node,
description: nodeDescription,
},
},
}));
}
}}
/>
{charLimit && (
<div
className={cn(
"text-left text-xs",
(nodeDescription?.length ?? 0) >= charLimit
? "text-error"
: "text-primary",
)}
data-testid="note_char_limit"
>
{nodeDescription?.length ?? 0}/{charLimit}
</div>
)}
</>
) : (
<div
className={cn(
"nodoubleclick generic-node-desc-text cursor-text word-break-break-word",
"nodoubleclick generic-node-desc-text h-full cursor-text word-break-break-word dark:text-note-placeholder",
description === "" || !description ? "font-light italic" : "",
)}
onDoubleClick={(e) => {
Expand All @@ -87,9 +119,14 @@ export default function NodeDescription({
}}
>
{description === "" || !description ? (
"Double Click to Edit Description"
emptyPlaceholder
) : (
<Markdown className="markdown prose flex flex-col text-primary word-break-break-word dark:prose-invert">
<Markdown
className={cn(
"markdown prose flex h-full w-full flex-col text-primary word-break-break-word dark:prose-invert",
mdClassName,
)}
>
{String(description)}
</Markdown>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default function NodeName({
const [nodeName, setNodeName] = useState(display_name);
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const setNode = useFlowStore((state) => state.setNode);

useEffect(() => {
if (!selected) {
setInputName(false);
Expand All @@ -29,7 +28,7 @@ export default function NodeName({
}, [display_name]);

return inputName ? (
<div>
<div className="w-full">
<InputComponent
onBlur={() => {
setInputName(false);
Expand Down Expand Up @@ -58,7 +57,7 @@ export default function NodeName({
/>
</div>
) : (
<div className="group flex items-center gap-1">
<div className="group flex w-full items-center gap-1">
<ShadTooltip content={display_name}>
<div
onDoubleClick={(event) => {
Expand All @@ -68,7 +67,7 @@ export default function NodeName({
event.preventDefault();
}}
data-testid={"title-" + display_name}
className="nodoubleclick generic-node-tooltip-div cursor-text text-primary"
className="nodoubleclick w-full cursor-text truncate text-primary"
>
{display_name}
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/CustomNodes/GenericNode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ export default function GenericNode({
>
<div
className={
"generic-node-title-arrangement rounded-full" +
(!showNode && " justify-center")
"generic-node-title-arrangement " +
(!showNode ? " justify-center" : "")
}
data-testid="generic-node-title-arrangement"
>
Expand Down
Loading

0 comments on commit 2fb7ce0

Please sign in to comment.