Skip to content

Commit 4ee2535

Browse files
anovazzi1autofix-ci[bot]lucaseduoliogabrielluizitalojohnny
authored
feature: add flow notes (#3460)
* 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]>
1 parent bc6e918 commit 4ee2535

File tree

34 files changed

+2071
-1066
lines changed

34 files changed

+2071
-1066
lines changed

poetry.lock

+1,055-971
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/backend/base/langflow/api/v1/chat.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ async def build_vertices(
329329
build_task = asyncio.create_task(await asyncio.to_thread(_build_vertex, vertex_id, graph))
330330
try:
331331
await build_task
332-
except asyncio.CancelledError:
332+
except asyncio.CancelledError as exc:
333+
logger.exception(exc)
333334
build_task.cancel()
334335
return
335336

src/backend/base/langflow/graph/graph/base.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
)
3232
from langflow.graph.schema import InterfaceComponentTypes, RunOutputs
3333
from langflow.graph.vertex.base import Vertex, VertexStates
34-
from langflow.graph.vertex.schema import NodeData
34+
from langflow.graph.vertex.schema import NodeData, NodeTypeEnum
3535
from langflow.graph.vertex.types import ComponentVertex, InterfaceVertex, StateVertex
3636
from langflow.logging.logger import LogConfig, configure
3737
from langflow.schema import Data
@@ -1628,6 +1628,8 @@ def _build_vertices(self) -> list["Vertex"]:
16281628
"""Builds the vertices of the graph."""
16291629
vertices: list["Vertex"] = []
16301630
for frontend_data in self._vertices:
1631+
if frontend_data.get("type") == NodeTypeEnum.NoteNode:
1632+
continue
16311633
try:
16321634
vertex_instance = self.get_vertex(frontend_data["id"])
16331635
except ValueError:

src/backend/base/langflow/graph/vertex/schema.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
from enum import Enum
2+
13
from typing_extensions import NotRequired, TypedDict
24

35

6+
class NodeTypeEnum(str, Enum):
7+
NoteNode = "noteNode"
8+
GenericNode = "genericNode"
9+
10+
411
class Position(TypedDict):
512
x: float
613
y: float
@@ -16,3 +23,4 @@ class NodeData(TypedDict):
1623
positionAbsolute: NotRequired[Position]
1724
selected: NotRequired[bool]
1825
parent_node_id: NotRequired[str]
26+
type: NotRequired[NodeTypeEnum]

src/backend/base/langflow/main.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
)
3030
from langflow.interface.types import get_and_cache_all_types_dict
3131
from langflow.interface.utils import setup_llm_caching
32+
from langflow.logging.logger import configure
3233
from langflow.services.deps import get_cache_service, get_settings_service, get_telemetry_service
3334
from langflow.services.plugins.langfuse_plugin import LangfuseInstance
3435
from langflow.services.utils import initialize_services, teardown_services
35-
from langflow.logging.logger import configure
3636

3737
# Ignore Pydantic deprecation warnings from Langchain
3838
warnings.filterwarnings("ignore", category=PydanticDeprecatedSince20)
@@ -133,8 +133,6 @@ def create_app():
133133
allow_headers=["*"],
134134
)
135135
app.add_middleware(JavaScriptMIMETypeMiddleware)
136-
# ! Deactivating this until we find a better solution
137-
# app.add_middleware(RequestCancelledMiddleware)
138136

139137
@app.middleware("http")
140138
async def flatten_query_string_lists(request: Request, call_next):

src/backend/tests/unit/graph/graph/test_graph_state_model.py

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def test_graph_state_model_serialization():
108108
assert serialized_state_model["chat_input"]["message"]["text"] == "Test Sender Name"
109109

110110

111+
@pytest.mark.skip(reason="Not implemented yet")
111112
def test_graph_state_model_json_schema():
112113
chat_input = ChatInput(_id="chat_input")
113114
chat_input.set(input_value="Test Sender Name")

src/frontend/package-lock.json

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/frontend/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"moment": "^2.30.1",
5353
"openseadragon": "^4.1.1",
5454
"p-debounce": "^4.0.0",
55+
"pako": "^2.1.0",
5556
"playwright": "^1.44.1",
5657
"react": "^18.3.1",
5758
"react-ace": "^11.0.1",

src/frontend/src/App.css

+8
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,11 @@ body {
161161
width: 100%;
162162
height: 100%;
163163
}
164+
.react-flow__resize-control.handle {
165+
width: 0.75rem!important;
166+
height: 0.75rem !important;
167+
background-color: white !important;
168+
border-color: var(--border) !important;
169+
z-index: 1000 !important;
170+
border-radius: 20% !important;
171+
}

src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx

+71-34
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,20 @@ export default function NodeDescription({
1010
description,
1111
selected,
1212
nodeId,
13+
emptyPlaceholder = "Double Click to Edit Description",
14+
charLimit,
15+
inputClassName,
16+
mdClassName,
17+
style,
1318
}: {
1419
description?: string;
1520
selected: boolean;
1621
nodeId: string;
22+
emptyPlaceholder?: string;
23+
charLimit?: number;
24+
inputClassName?: string;
25+
mdClassName?: string;
26+
style?: React.CSSProperties;
1727
}) {
1828
const [inputDescription, setInputDescription] = useState(false);
1929
const [nodeDescription, setNodeDescription] = useState(description);
@@ -31,35 +41,20 @@ export default function NodeDescription({
3141
}, [description]);
3242

3343
return (
34-
<div className="generic-node-desc">
44+
<div
45+
className={cn(
46+
"generic-node-desc",
47+
!inputDescription ? "overflow-auto" : "",
48+
)}
49+
>
3550
{inputDescription ? (
36-
<Textarea
37-
className="nowheel min-h-40"
38-
autoFocus
39-
onBlur={() => {
40-
setInputDescription(false);
41-
setNodeDescription(nodeDescription);
42-
setNode(nodeId, (old) => ({
43-
...old,
44-
data: {
45-
...old.data,
46-
node: {
47-
...old.data.node,
48-
description: nodeDescription,
49-
},
50-
},
51-
}));
52-
}}
53-
value={nodeDescription}
54-
onChange={(e) => setNodeDescription(e.target.value)}
55-
onKeyDown={(e) => {
56-
handleKeyDown(e, nodeDescription, "");
57-
if (
58-
e.key === "Enter" &&
59-
e.shiftKey === false &&
60-
e.ctrlKey === false &&
61-
e.altKey === false
62-
) {
51+
<>
52+
<Textarea
53+
maxLength={charLimit}
54+
className={cn("nowheel h-full", inputClassName)}
55+
autoFocus
56+
style={style}
57+
onBlur={() => {
6358
setInputDescription(false);
6459
setNodeDescription(nodeDescription);
6560
setNode(nodeId, (old) => ({
@@ -72,13 +67,50 @@ export default function NodeDescription({
7267
},
7368
},
7469
}));
75-
}
76-
}}
77-
/>
70+
}}
71+
value={nodeDescription}
72+
onChange={(e) => setNodeDescription(e.target.value)}
73+
onKeyDown={(e) => {
74+
handleKeyDown(e, nodeDescription, "");
75+
if (
76+
e.key === "Enter" &&
77+
e.shiftKey === false &&
78+
e.ctrlKey === false &&
79+
e.altKey === false
80+
) {
81+
setInputDescription(false);
82+
setNodeDescription(nodeDescription);
83+
setNode(nodeId, (old) => ({
84+
...old,
85+
data: {
86+
...old.data,
87+
node: {
88+
...old.data.node,
89+
description: nodeDescription,
90+
},
91+
},
92+
}));
93+
}
94+
}}
95+
/>
96+
{charLimit && (
97+
<div
98+
className={cn(
99+
"text-left text-xs",
100+
(nodeDescription?.length ?? 0) >= charLimit
101+
? "text-error"
102+
: "text-primary",
103+
)}
104+
data-testid="note_char_limit"
105+
>
106+
{nodeDescription?.length ?? 0}/{charLimit}
107+
</div>
108+
)}
109+
</>
78110
) : (
79111
<div
80112
className={cn(
81-
"nodoubleclick generic-node-desc-text cursor-text word-break-break-word",
113+
"nodoubleclick generic-node-desc-text h-full cursor-text word-break-break-word dark:text-note-placeholder",
82114
description === "" || !description ? "font-light italic" : "",
83115
)}
84116
onDoubleClick={(e) => {
@@ -87,9 +119,14 @@ export default function NodeDescription({
87119
}}
88120
>
89121
{description === "" || !description ? (
90-
"Double Click to Edit Description"
122+
emptyPlaceholder
91123
) : (
92-
<Markdown className="markdown prose flex flex-col text-primary word-break-break-word dark:prose-invert">
124+
<Markdown
125+
className={cn(
126+
"markdown prose flex h-full w-full flex-col text-primary word-break-break-word dark:prose-invert",
127+
mdClassName,
128+
)}
129+
>
93130
{String(description)}
94131
</Markdown>
95132
)}

src/frontend/src/CustomNodes/GenericNode/components/NodeName/index.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export default function NodeName({
1717
const [nodeName, setNodeName] = useState(display_name);
1818
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
1919
const setNode = useFlowStore((state) => state.setNode);
20-
2120
useEffect(() => {
2221
if (!selected) {
2322
setInputName(false);
@@ -29,7 +28,7 @@ export default function NodeName({
2928
}, [display_name]);
3029

3130
return inputName ? (
32-
<div>
31+
<div className="w-full">
3332
<InputComponent
3433
onBlur={() => {
3534
setInputName(false);
@@ -58,7 +57,7 @@ export default function NodeName({
5857
/>
5958
</div>
6059
) : (
61-
<div className="group flex items-center gap-1">
60+
<div className="group flex w-full items-center gap-1">
6261
<ShadTooltip content={display_name}>
6362
<div
6463
onDoubleClick={(event) => {
@@ -68,7 +67,7 @@ export default function NodeName({
6867
event.preventDefault();
6968
}}
7069
data-testid={"title-" + display_name}
71-
className="nodoubleclick generic-node-tooltip-div cursor-text text-primary"
70+
className="nodoubleclick w-full cursor-text truncate text-primary"
7271
>
7372
{display_name}
7473
</div>

src/frontend/src/CustomNodes/GenericNode/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ export default function GenericNode({
287287
>
288288
<div
289289
className={
290-
"generic-node-title-arrangement rounded-full" +
291-
(!showNode && " justify-center")
290+
"generic-node-title-arrangement " +
291+
(!showNode ? " justify-center" : "")
292292
}
293293
data-testid="generic-node-title-arrangement"
294294
>

0 commit comments

Comments
 (0)