Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

make node not draggable when editing the name #52

Merged
merged 2 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ jest.mock("../latex/Katex");

test("should render the name only", () => {
const handleNameChange = jest.fn();
const handleEditingChange = jest.fn();
render(
<EditableName
name="abc"
operationData={null}
onEditingChange={handleEditingChange}
onNameChange={handleNameChange}
/>,
);
Expand All @@ -19,11 +21,13 @@ test("should render the name only", () => {

test("should render the name and operation text", () => {
const operationData = getOperationData();
const handleEditingChange = jest.fn();
const handleNameChange = jest.fn();
render(
<EditableName
name="abc"
operationData={operationData}
onEditingChange={handleEditingChange}
onNameChange={handleNameChange}
/>,
);
Expand All @@ -32,57 +36,72 @@ test("should render the name and operation text", () => {
expect(screen.getByText("(Operation 1)")).toBeInTheDocument();
});

test("should trigger event with updated name when blurred", () => {
test("should trigger events when blurred", () => {
const handleEditingChange = jest.fn();
const handleNameChange = jest.fn();
render(
<EditableName
name="abc"
operationData={null}
onEditingChange={handleEditingChange}
onNameChange={handleNameChange}
/>,
);

clickEditIcon();
expect(handleEditingChange).toBeCalledWith(true);

changeName("123");
const input = getEditingTextbox();
fireEvent.blur(input);

expect(handleEditingChange).toBeCalledWith(false);
expect(handleNameChange).toBeCalledWith("123");
});

test("should trigger event with updated name when Enter is pressed", () => {
test("should trigger events when Enter is pressed", () => {
const handleEditingChange = jest.fn();
const handleNameChange = jest.fn();
render(
<EditableName
name="abc"
operationData={null}
onEditingChange={handleEditingChange}
onNameChange={handleNameChange}
/>,
);

clickEditIcon();
expect(handleEditingChange).toBeCalledWith(true);

changeName("123");
const input = getEditingTextbox();
fireEvent.keyDown(input, { key: "Enter" });

expect(handleEditingChange).toBeCalledWith(false);
expect(handleNameChange).toBeCalledWith("123");
});

test("should not trigger event with old name when Escape is pressed", () => {
test("should trigger events when Escape is pressed", () => {
const handleEditingChange = jest.fn();
const handleNameChange = jest.fn();
render(
<EditableName
name="abc"
operationData={null}
onEditingChange={handleEditingChange}
onNameChange={handleNameChange}
/>,
);

clickEditIcon();
expect(handleEditingChange).toBeCalledWith(true);

changeName("123");
const input = getEditingTextbox();
fireEvent.keyDown(input, { key: "Escape" });

expect(handleEditingChange).toBeCalledWith(false);
expect(handleNameChange).not.toBeCalled();
});

Expand Down
25 changes: 19 additions & 6 deletions interactive-computational-graph/src/reactflow/EditableName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,59 @@ import Katex from "../latex/Katex";
interface EditableNameProps {
name: string;
operationData: OperationNodeData | null;
onEditingChange: (isEditing: boolean) => void;
onNameChange: (name: string) => void;
}

const EditableName: FunctionComponent<EditableNameProps> = ({
name,
operationData,
onEditingChange,
onNameChange,
}) => {
const [isEditing, setIsEditing] = useState(false);
const [editingName, setEditingName] = useState(name);

const updateEditing = useCallback(
(isEditing: boolean) => {
setIsEditing(isEditing);
onEditingChange(isEditing);
},
[onEditingChange],
);

const handleChange = useCallback((name: string) => {
setEditingName(name);
}, []);

const handleSaveName = useCallback(
(name: string) => {
onNameChange(name);
setIsEditing(false);
updateEditing(false);
},
[onNameChange],
[onNameChange, updateEditing],
);

const handleKeyDown = useCallback(
(e: KeyboardEvent) => {
if (e.key === "Enter") {
onNameChange(editingName);
setIsEditing(false);
updateEditing(false);
} else if (e.key === "Escape") {
setEditingName(name);
setIsEditing(false);
updateEditing(false);
}
},
[editingName, name, onNameChange],
[editingName, name, onNameChange, updateEditing],
);

return (
<Stack direction="row" alignItems="center" justifyContent="space-between">
{isEditing ? (
<TextField
inputProps={{
"aria-label": "editingName",
}}
size="small"
value={editingName}
onChange={(event) => {
Expand Down Expand Up @@ -93,7 +106,7 @@ const EditableName: FunctionComponent<EditableNameProps> = ({
aria-label="edit"
size="small"
onClick={() => {
setIsEditing(true);
updateEditing(true);
}}
>
<EditIcon fontSize="small" />
Expand Down
32 changes: 31 additions & 1 deletion interactive-computational-graph/src/reactflow/NodeTitle.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import type OperationNodeData from "../features/OperationNodeData";
import NodeTitle from "./NodeTitle";

Expand All @@ -22,6 +22,36 @@ test("should render the name", () => {
expect(screen.getByText("abc")).toBeInTheDocument();
});

test("should not have draggable class when editing the name", () => {
const operationData = getOperationData();
const handleNameChange = jest.fn();
render(
<NodeTitle
id="1"
name="abc"
operationData={operationData}
backgroundColor="white"
isDarkMode={false}
isHighlighted={false}
onNameChange={handleNameChange}
/>,
);

const nodeTitle = screen.getByTestId("node-title-1");
const editIcon = screen.getByLabelText("edit");

expect(nodeTitle).toHaveClass("drag-handle");

fireEvent.click(editIcon);

expect(nodeTitle).not.toHaveClass("drag-handle");

const editingInput = screen.getByLabelText("editingName");
fireEvent.blur(editingInput);

expect(nodeTitle).toHaveClass("drag-handle");
});

test("should not have striped animation when not highlighted", () => {
const operationData = getOperationData();
const handleNameChange = jest.fn();
Expand Down
19 changes: 17 additions & 2 deletions interactive-computational-graph/src/reactflow/NodeTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
import { Box, Stack } from "@mui/material";
import { useMemo, type FunctionComponent } from "react";
import { useCallback, useMemo, useState, type FunctionComponent } from "react";
import type OperationNodeData from "../features/OperationNodeData";
import EditableName from "./EditableName";
import "./NodeTitle.css";
Expand Down Expand Up @@ -31,11 +31,25 @@ const NodeTitle: FunctionComponent<NodeTitleProps> = ({
return isDarkMode ? "striped-animation-dark" : "striped-animation-light";
}, [isDarkMode, isHighlighted]);

const [isEditingName, setIsEditingName] = useState(false);

const getClassName = useCallback(() => {
if (isEditingName) {
return `${animationClassName}`;
} else {
return `drag-handle ${animationClassName}`;
}
}, [animationClassName, isEditingName]);

const handleEditingChange = useCallback((isEditing: boolean) => {
setIsEditingName(isEditing);
}, []);

return (
<Box
data-testid={`node-title-${id}`}
// corresponds to dragHandle when creating new reactflow.Node
className={`drag-handle ${animationClassName}`}
className={getClassName()}
display="flex"
sx={{ backgroundColor }}
p={0.5}
Expand All @@ -48,6 +62,7 @@ const NodeTitle: FunctionComponent<NodeTitleProps> = ({
<EditableName
name={name}
operationData={operationData}
onEditingChange={handleEditingChange}
onNameChange={onNameChange}
/>
</Box>
Expand Down