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

chore: refactor query duplication flow #36915

Merged
merged 21 commits into from
Oct 24, 2024
Merged

Conversation

ayushpahwa
Copy link
Contributor

@ayushpahwa ayushpahwa commented Oct 16, 2024

Description

This PR refactors the action duplication saga and action calls to remove dependency on pageID. As far as CE code is concerned, this PR doesn't change any functionality for the end user. Those changes are done for workflows editor in EE.

Fixes #36886

Automation

/test all

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/11462274307
Commit: 04dfbfb
Cypress dashboard.
Tags: @tag.All
Spec:


Tue, 22 Oct 2024 16:21:32 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features

    • Introduced a new hook, useHandleDuplicateClick, enhancing action duplication functionality.
    • Added a new interface and function for generating destination ID information.
  • Bug Fixes

    • Updated action request structure to use destinationEntityId for consistency across components.
  • Documentation

    • Enhanced success message flexibility for action copy notifications.
  • Tests

    • Added unit tests for the ActionEntityContextMenu component to ensure proper functionality and rendering.
  • Refactor

    • Improved context menu handling based on entity types for better user experience.

@github-actions github-actions bot added the skip-changelog Adding this label to a PR prevents it from being listed in the changelog label Oct 16, 2024
Copy link

⚠️ Cyclic Dependency Check:

This PR has increased the number of cyclic dependencies by 1, when compared with the release branch.

Refer this document to identify the cyclic dependencies introduced by this PR.

@ayushpahwa ayushpahwa added the ok-to-test Required label for CI label Oct 16, 2024
@github-actions github-actions bot added Enhancement New feature or request Workflows Pod Issues that the workflows team owns Workflows Product Issues related to the workflows product and removed Enhancement New feature or request labels Oct 16, 2024
Copy link
Member

@hetunandu hetunandu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-actions github-actions bot added the Enhancement New feature or request label Oct 18, 2024
@ayushpahwa ayushpahwa requested a review from hetunandu October 18, 2024 15:56
import { useCallback } from "react";
import { useDispatch } from "react-redux";

function useHandleDuplicateClick() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ayushpahwa any unit test case coverage needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a hook which is passing on the action as per the input. I have added test for the rendering of the action menu which was the actual change and also covers the functionality of this hook. This test can be enhanced to introduce coverage of other options also but since they are already covered in cypress, I have just left a TODO comment for now for the same.

hetunandu
hetunandu previously approved these changes Oct 22, 2024
@hetunandu hetunandu requested a review from sagar-qa007 October 22, 2024 05:02
@ayushpahwa ayushpahwa marked this pull request as ready for review October 23, 2024 05:57
Copy link
Contributor

coderabbitai bot commented Oct 23, 2024

Walkthrough

The changes introduce a new custom React hook, useHandleDuplicateClick, which facilitates the duplication of actions within the PluginActionEditor module. This hook interacts with the Redux store to dispatch actions related to copying actions, enhancing the overall functionality. Additionally, modifications are made to several action-related functions and constants to accommodate the new destinationEntityId parameter, improving the structure of action payloads. A new test file is also added to ensure the functionality of the ActionEntityContextMenu component.

Changes

File Change Summary
app/client/src/PluginActionEditor/hooks/index.ts Added export for useHandleDuplicateClick hook.
app/client/src/PluginActionEditor/hooks/useHandleDuplicateClick.ts Introduced useHandleDuplicateClick hook for handling action duplication.
app/client/src/actions/pluginActionActions.ts Updated copyActionRequest and copyActionError to use destinationEntityId.
app/client/src/ce/constants/messages.ts Modified ACTION_COPY_SUCCESS message format for better flexibility.
app/client/src/ce/pages/Editor/AppPluginActionEditor/components/ToolbarMenu/Copy.tsx Changed dispatched action property from destinationPageId to destinationEntityId.
app/client/src/ce/sagas/helpers.ts Added GenerateDestinationIdInfoReturnType interface and generateDestinationIdInfoForQueryDuplication function.
app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.test.tsx Added unit tests for ActionEntityContextMenu component.
app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx Updated EntityContextMenuProps to be exported and modified action handling logic.
app/client/src/pages/Editor/Explorer/Actions/MoreActionsMenu.tsx Renamed destinationPageId to destinationEntityId in copyActionToPage.
app/client/src/sagas/ActionSagas.ts Updated sagas to use destinationEntityId and refined error handling.

Assessment against linked issues

Objective Addressed Explanation
Allow queries to be duplicated in workflow editor (#36886)

Possibly related PRs

Suggested labels

Bug, High, Production, Needs Triaging, Query & JS Pod, Integrations Product

Suggested reviewers

  • ankitakinger
  • rishabhrathod01

🎉 In the realm of code where actions play,
A hook was born to copy away!
With destinationId now in sight,
Duplication's ease brings pure delight!
Tests ensure all works just right,
In our editor's glow, we code through the night! 🌙✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot removed the Enhancement New feature or request label Oct 23, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (11)
app/client/src/PluginActionEditor/hooks/index.ts (1)

Line range hint 1-7: Consider grouping exports by source

The exports could be organized by grouping EE imports together and local imports separately for better maintainability.

+// Enterprise Edition hooks
 export { useActionSettingsConfig } from "ee/PluginActionEditor/hooks/useActionSettingsConfig";
 export { useHandleDeleteClick } from "ee/PluginActionEditor/hooks/useHandleDeleteClick";
-export { useHandleDuplicateClick } from "./useHandleDuplicateClick";
 export { useHandleRunClick } from "ee/PluginActionEditor/hooks/useHandleRunClick";
 export { useBlockExecution } from "ee/PluginActionEditor/hooks/useBlockExecution";
 export { useAnalyticsOnRunClick } from "ee/PluginActionEditor/hooks/useAnalyticsOnRunClick";
+
+// Community Edition hooks
+export { useHandleDuplicateClick } from "./useHandleDuplicateClick";
app/client/src/PluginActionEditor/hooks/useHandleDuplicateClick.ts (1)

6-24: Consider adding TypeScript types for better type safety.

While the implementation is clean and follows React best practices, consider adding explicit types:

-function useHandleDuplicateClick() {
+interface DuplicateClickHookResult {
+  handleDuplicateClick: (destinationEntityId: string) => void;
+}
+
+function useHandleDuplicateClick(): DuplicateClickHookResult {
app/client/src/ce/pages/Editor/AppPluginActionEditor/components/ToolbarMenu/Copy.tsx (1)

Line range hint 16-25: Consider adding type safety to the action payload.

While the implementation is correct, consider creating a dedicated type for the action payload to improve maintainability.

interface CopyActionPayload {
  id: string;
  destinationEntityId: string;
  name: string;
}
app/client/src/ce/sagas/helpers.ts (1)

18-28: Consider adding parameter validation.

The implementation is clean and follows the single responsibility principle. However, consider adding validation for the destinationEntityId parameter to prevent potential issues with empty or invalid IDs.

 export function generateDestinationIdInfoForQueryDuplication(
   destinationEntityId: string,
   parentEntityKey: CreateNewActionKeyInterface,
 ): GenerateDestinationIdInfoReturnType {
+  if (!destinationEntityId?.trim()) {
+    throw new Error("destinationEntityId cannot be empty");
+  }
   if (parentEntityKey === CreateNewActionKey.PAGE) {
     return { pageId: destinationEntityId };
   }
app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.test.tsx (3)

1-28: Consider organizing imports by CE/EE separation.

The imports mix paths from both CE and EE. Consider grouping them separately for better maintainability.

// CE imports
import React from "react";
import { fireEvent, render, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { Provider } from "react-redux";
import { lightTheme } from "selectors/themeSelectors";
import { ThemeProvider } from "styled-components";
import configureStore from "redux-mock-store";
import { PluginType } from "entities/Action";

// EE imports
import {
  ActionEntityContextMenu,
  type EntityContextMenuProps,
} from "./ActionEntityContextMenu";
import { FilesContextProvider } from "../Files/FilesContextProvider";
import { ActionParentEntityType } from "ee/entities/Engine/actionHelpers";
// ... rest of EE imports

31-33: Extract page IDs as named constants.

Consider moving these IDs to a constants object at the top of the file for better maintainability.

+const PAGE_IDS = {
+  PAGE_1: "605c435a91dea93f0eaf91ba",
+  PAGE_2: "605c435a91dea93f0eaf91bc",
+  BASE_PAGE_2: "605c435a91dea93f0eaf91bc",
+} as const;
-const page1Id = "605c435a91dea93f0eaf91ba";
-const page2Id = "605c435a91dea93f0eaf91bc";
-const basePage2Id = "605c435a91dea93f0eaf91bc";

147-156: Simplify type definition using type inference.

The explicit type definition for the actions array can be simplified by letting TypeScript infer the type from store.getActions().

-    let actions: Array<
-      ReduxAction<{
-        payload: {
-          id: string;
-          destinationEntityId: string;
-          name: string;
-        };
-      }>
-    > = [];
+    let actions = [] as ReturnType<typeof store.getActions>;
app/client/src/pages/Editor/Explorer/Actions/MoreActionsMenu.tsx (1)

Line range hint 153-154: Consider implementing the suggested UX improvement.

The existing comment suggests moving the menu visibility logic outside. This would indeed improve UX by preventing users from seeing empty or irrelevant menu options.

Would you like me to propose an implementation for this improvement?

app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx (1)

50-51: Consider adding type validation for parentEntityType.

While the context destructuring looks good, consider adding runtime type validation for parentEntityType to ensure it matches ActionParentEntityType.

  const { menuItems, parentEntityId, parentEntityType } = context;
+ if (!Object.values(ActionParentEntityType).includes(parentEntityType)) {
+   console.warn(`Invalid parentEntityType: ${parentEntityType}`);
+ }
app/client/src/sagas/ActionSagas.ts (2)

774-780: Add logging for empty destinationEntityIdInfo

Currently, if destinationEntityIdInfo is empty, the saga returns without any notification. Consider adding a log or error message to inform about this scenario, which could aid in debugging.


867-870: Include destinationEntityIdInfo in error payload

When dispatching copyActionError, consider including destinationEntityIdInfo in the error payload for better context and easier debugging.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a8da0e1 and 04dfbfb.

📒 Files selected for processing (10)
  • app/client/src/PluginActionEditor/hooks/index.ts (1 hunks)
  • app/client/src/PluginActionEditor/hooks/useHandleDuplicateClick.ts (1 hunks)
  • app/client/src/actions/pluginActionActions.ts (3 hunks)
  • app/client/src/ce/constants/messages.ts (2 hunks)
  • app/client/src/ce/pages/Editor/AppPluginActionEditor/components/ToolbarMenu/Copy.tsx (1 hunks)
  • app/client/src/ce/sagas/helpers.ts (1 hunks)
  • app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.test.tsx (1 hunks)
  • app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx (4 hunks)
  • app/client/src/pages/Editor/Explorer/Actions/MoreActionsMenu.tsx (1 hunks)
  • app/client/src/sagas/ActionSagas.ts (10 hunks)
🧰 Additional context used
🔇 Additional comments (12)
app/client/src/PluginActionEditor/hooks/index.ts (1)

3-3: Verify architectural decision: Local vs EE import pattern

The new hook is imported from a local path while other hooks are imported from the EE directory. This might indicate an architectural change moving functionality from EE to CE.

Let's verify the import patterns in the codebase:

✅ Verification successful

Let me verify the architectural pattern further by checking the CE implementation and imports:

This will help us understand where the new hook is implemented and how it's being used across the codebase.


Local hook implementation follows correct architectural pattern

The import pattern is consistent with the codebase architecture:

  • Other hooks in EE directory (useHandleDeleteClick, useHandleRunClick, etc.) are re-exports from CE implementations
  • The new useHandleDuplicateClick hook follows the same pattern by being implemented directly in CE
  • The hook is properly scoped within the PluginActionEditor module
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check import patterns for hooks in PluginActionEditor
rg -g '*.{ts,tsx}' -l "from.*PluginActionEditor/hooks" | xargs rg "from.*PluginActionEditor/hooks"

# Check if there are other local hook imports
rg -g '*.{ts,tsx}' --glob '!*.test.*' -l "from.*./.*hook" ./app/client/src/PluginActionEditor/

Length of output: 3345


Script:

#!/bin/bash
# Check CE implementation of hooks
fd "useHandleDuplicateClick.ts" app/client/src/
rg -g '*.{ts,tsx}' "from.*useHandleDuplicateClick" app/client/src/

Length of output: 301

app/client/src/PluginActionEditor/hooks/useHandleDuplicateClick.ts (2)

1-5: LGTM! Clean and focused imports.

The imports are well-organized and include all necessary dependencies for the hook's functionality.


6-24: Add unit tests for the hook.

While the functionality is covered by Cypress tests, adding unit tests would improve maintainability and catch potential issues earlier in the development cycle.

Let's check if there are any existing test files for hooks:

Would you like me to help create a unit test file for this hook?

✅ Verification successful

Let me gather more information about the testing setup in this codebase to provide a more accurate verification.

The first script will help us understand if there are test files at the component level. The second script will show us how hooks are typically tested in this codebase, and the third will reveal any test utilities that might be helpful for testing hooks. This will give us a better picture of the testing practices in the project.


Let me check the existing hook test to understand the testing pattern used in this codebase.

This will help us understand:

  1. How hooks are currently tested in this codebase
  2. What test setup is available
  3. How Redux-related functionality is typically tested

Add unit tests following the established pattern

Based on the existing hook test patterns in the codebase, create a test file at app/client/src/PluginActionEditor/hooks/useHandleDuplicateClick.test.tsx with the following test cases:

  • Mock dependencies (useDispatch, usePluginActionContext)
  • Test successful dispatch of copyActionRequest with correct parameters
  • Test when action context is not available
  • Verify memoization by checking if callback changes when dependencies change

Example test structure:

import { renderHook } from "@testing-library/react-hooks/dom";
import { useDispatch } from "react-redux";
import { usePluginActionContext } from "../PluginActionContext";
import { copyActionRequest } from "../store";
import { useHandleDuplicateClick } from "./useHandleDuplicateClick";

jest.mock("react-redux");
jest.mock("../PluginActionContext");
jest.mock("../store");
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing hook test files to maintain consistency
fd -e test.ts -e test.tsx . app/client/src/PluginActionEditor/hooks/

Length of output: 70


Script:

#!/bin/bash
# Check for test files in the parent directories to understand the testing patterns
fd -e test.ts -e test.tsx . app/client/src/PluginActionEditor/

# Look for similar hook test patterns in the codebase
fd -e test.ts -e test.tsx . app/client/src | rg -l "hook|Hook"

# Check if there are any test utilities or setup files
fd -e ts -e tsx . app/client/src | rg -l "test.*setup|test.*utils"

Length of output: 744


Script:

#!/bin/bash
# Check the content of the existing hook test to understand the testing pattern
cat app/client/src/PluginActionEditor/components/PluginActionForm/hooks/useChangeActionCall.test.tsx

# Look for test setup files in the project root
fd -e ts -e tsx -e js . | rg -l "jest.setup|test.setup"

# Check for any Redux-related test utilities since the hook uses dispatch
rg -l "redux.*test|test.*redux" app/client/src/

Length of output: 6667

app/client/src/pages/Editor/Explorer/Actions/MoreActionsMenu.tsx (1)

66-68: LGTM: Parameter rename aligns with refactoring goals.

The change from destinationPageId to destinationEntityId in the copy action payload aligns with the PR's objective to refactor the query duplication flow.

app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx (2)

23-23: LGTM! Clean interface and import changes.

The exported interface and new imports align well with the refactoring objectives for query duplication.

Also applies to: 37-37, 39-47


Line range hint 58-67: LGTM! Clean action handler refactoring.

The transition from page-specific to entity-based copying is well implemented. The useCallback dependency array is correctly maintained.

app/client/src/actions/pluginActionActions.ts (3)

24-24: LGTM: Import for new type from EE module.

The import aligns with the PR objective of refactoring the duplication flow.


248-248: LGTM: Updated error payload structure.

The change to use destinationEntityIdInfo with the new type from EE maintains consistency with the refactoring approach.


229-231: LGTM: Updated payload type for action duplication.

The change from destinationPageId to destinationEntityId aligns with the refactoring goal of eliminating page ID dependency.

Let's verify the consistency of this change across the codebase:

app/client/src/ce/constants/messages.ts (2)

340-341: LGTM! Improved message flexibility

The conditional message formatting allows for better reusability when pageName is empty.


1734-1734: LGTM! Follows constant naming convention

The new CONTEXT_DUPLICATE constant follows the established pattern for context action messages.

app/client/src/sagas/ActionSagas.ts (1)

806-814: Verify response.data.pageId existence

In the if block, you're accessing response.data.pageId, but there's a comment indicating it might not be present. Ensure that pageId exists on response.data to prevent potential runtime errors.

@@ -17,7 +17,7 @@ export const Copy = () => {
dispatch(
copyActionRequest({
id: action.id,
destinationPageId: pageId,
destinationEntityId: pageId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Parameter renaming needs to be completed across the codebase

The verification reveals inconsistent parameter naming. While destinationEntityId is used in the new copy functionality, there are still multiple occurrences of destinationPageId across the codebase that need to be updated for consistency:

  • Frontend files still using destinationPageId:

    • app/client/src/sagas/ActionSagas.ts
    • app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx
    • app/client/src/pages/Editor/Explorer/Actions/MoreActionsMenu.tsx
    • app/client/src/ce/sagas/JSActionSagas.ts
    • app/client/src/api/ActionAPI.tsx
  • Backend files also using destinationPageId:

    • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutCollectionServiceCEImpl.java
    • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java

Please update all occurrences to maintain consistency with the new destinationEntityId parameter name.

🔗 Analysis chain

Verify consistent parameter naming across the codebase.

The change from destinationPageId to destinationEntityId looks good and aligns with the refactoring goals.

Let's verify the consistent usage across the codebase:


The previous commands failed due to unsupported file type flags. Let's try without them and get a broader context of the changes. The new commands will help us:

  1. Find any remaining instances of the old parameter name
  2. Verify the usage of the new parameter name
  3. Understand the implementation context of the copyActionRequest
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining instances of destinationPageId
rg "destinationPageId" --type ts --type tsx

# Search for new parameter usage
rg "destinationEntityId.*copyActionRequest" --type ts --type tsx

Length of output: 166


Script:

#!/bin/bash
# Search for any remaining instances of destinationPageId without file type flags
rg "destinationPageId"

# Search for new parameter usage
rg "destinationEntityId.*copyActionRequest"

# Let's also check for the action handler implementation
rg "copyActionRequest" -A 5

Length of output: 9829

Comment on lines +13 to +16
// This function is extended in EE. Please check the EE implementation before any modification.
export interface GenerateDestinationIdInfoReturnType {
pageId?: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Interface implementation needs to be moved to EE directory

The interface is currently defined in CE but imported from EE (import type { GenerateDestinationIdInfoReturnType } from "ee/sagas/helpers"). This mismatch needs to be addressed:

  • Move the interface definition from app/client/src/ce/sagas/helpers.ts to the corresponding EE file
  • Update imports to reference the correct EE location

The current setup could lead to import resolution issues and doesn't align with the codebase's CE/EE separation pattern.

🔗 Analysis chain

LGTM! Verify EE implementation compatibility.

The interface is well-defined and follows TypeScript best practices.

Let's verify the EE implementation:


The previous search in the ee/ directory failed because the directory might be named differently or located elsewhere. Let's search the entire codebase for any references or extensions of this interface.


Let's check for EE implementations since the comment indicates this function is extended in EE. The previous search only found the CE implementation, so we need to look for actual extensions or usages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any EE-specific extensions of this interface
rg -A 5 "interface GenerateDestinationIdInfoReturnType" "ee/"

Length of output: 105


Script:

#!/bin/bash
# Let's try searching in the entire codebase for EE-specific extensions
rg -g '!node_modules' -g '!dist' -A 5 "interface GenerateDestinationIdInfoReturnType"

# Also search for any files that might contain EE implementations
fd -g '*.ts' -g '*.js' -E 'node_modules' -E 'dist' -x rg -l "GenerateDestinationIdInfoReturnType"

Length of output: 718


Script:

#!/bin/bash
# Let's search for any EE-specific implementations or extensions
rg -g '!node_modules' -g '!dist' -A 10 "generateDestinationIdInfoForQueryDuplication" --type ts

# Also check for any imports of this interface
rg -g '!node_modules' -g '!dist' "import.*GenerateDestinationIdInfoReturnType" --type ts

Length of output: 2599

Comment on lines +94 to +169
it("renders context menu with correct options for application editor", async () => {
store = mockStore(defaultState);
const { findByText, getByRole } = render(
<Provider store={store}>
<ThemeProvider theme={lightTheme}>
<FilesContextProvider {...defaultContext}>
<ActionEntityContextMenu {...defaultProps} />
</FilesContextProvider>
</ThemeProvider>
</Provider>,
);
const triggerToOpenMenu = getByRole("button");

act(() => {
fireEvent.click(triggerToOpenMenu);
});

await waitFor(() => {
expect(triggerToOpenMenu.parentNode).toHaveAttribute(
"aria-expanded",
"true",
);
});

// In context of pages, the copy to page option will be shown
const copyQueryToPageOptions = await findByText(
createMessage(CONTEXT_COPY),
);

expect(await findByText(createMessage(CONTEXT_RENAME))).toBeInTheDocument();
expect(await findByText(createMessage(CONTEXT_DELETE))).toBeInTheDocument();
expect(await findByText(createMessage(CONTEXT_MOVE))).toBeInTheDocument();
expect(
await findByText(createMessage(CONTEXT_SHOW_BINDING)),
).toBeInTheDocument();
expect(copyQueryToPageOptions).toBeInTheDocument();

// Now we click on the copy to page option
act(() => {
fireEvent.click(copyQueryToPageOptions);
});

// Now a menu with the list of pages will show up
const copyQueryToPageSubOptionPage1 = await findByText("Page1");

expect(copyQueryToPageSubOptionPage1).toBeInTheDocument();
expect(await findByText("Page2")).toBeInTheDocument();

// Clicking on the page will trigger the correct action
act(() => {
fireEvent.click(copyQueryToPageSubOptionPage1);
});

let actions: Array<
ReduxAction<{
payload: {
id: string;
destinationEntityId: string;
name: string;
};
}>
> = [];

await waitFor(() => {
actions = store.getActions();
});

expect(actions.length).toBe(1);
expect(actions[0].type).toBe(ReduxActionTypes.COPY_ACTION_INIT);
expect(actions[0].payload).toEqual({
destinationEntityId: page1Id,
id: "test-action-id",
name: "test-action",
});
});
// TODO: add tests for all options rendered in the context menu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Expand test coverage for all context menu actions.

The current test only verifies the copy action. Consider adding test cases for:

  • Delete action
  • Rename action
  • Move action
  • Show binding functionality
  • Permission-based rendering (when canManageAction/canDeleteAction are false)

Would you like me to help generate the additional test cases?

Comment on lines +66 to 68
destinationEntityId: pageId,
name: actionName,
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider unifying the parameter naming between copy and move operations.

The copy operation uses destinationEntityId while the move operation still uses destinationPageId. This inconsistency might cause confusion.

Consider updating the move operation to match:

  moveActionRequest({
    id: actionId,
-   destinationPageId,
+   destinationEntityId: destinationPageId,
    originalPageId: propPageId ?? "",
    name: actionName,
  }),

Also applies to: 73-80

Comment on lines +134 to +153
onSelect:
parentEntityType === ActionParentEntityType.PAGE
? noop
: () => {
copyAction(props.id, props.name, parentEntityId);
},
label: createMessage(
parentEntityType === ActionParentEntityType.PAGE
? CONTEXT_COPY
: CONTEXT_DUPLICATE,
),
children:
parentEntityType === ActionParentEntityType.PAGE &&
menuPages.length > 0 &&
menuPages.map((page) => {
return {
...page,
onSelect: () => copyAction(props.id, props.name, page.id),
};
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider extracting copy action logic into separate functions.

The copy action configuration is complex and would benefit from being broken down into smaller, more testable functions.

Consider this refactoring:

const getCopyActionLabel = (parentEntityType: ActionParentEntityType) => 
  parentEntityType === ActionParentEntityType.PAGE
    ? createMessage(CONTEXT_COPY)
    : createMessage(CONTEXT_DUPLICATE);

const getCopyActionHandler = (
  parentEntityType: ActionParentEntityType,
  id: string,
  name: string,
  parentEntityId: string,
) =>
  parentEntityType === ActionParentEntityType.PAGE
    ? noop
    : () => copyAction(id, name, parentEntityId);

const getCopyActionChildren = (
  parentEntityType: ActionParentEntityType,
  menuPages: Array<any>,
  id: string,
  name: string,
) =>
  parentEntityType === ActionParentEntityType.PAGE && menuPages.length > 0
    ? menuPages.map((page) => ({
        ...page,
        onSelect: () => copyAction(id, name, page.id),
      }))
    : undefined;

// In optionsTree:
{
  value: "copy",
  onSelect: getCopyActionHandler(parentEntityType, props.id, props.name, parentEntityId),
  label: getCopyActionLabel(parentEntityType),
  children: getCopyActionChildren(parentEntityType, menuPages, props.id, props.name),
}

Comment on lines +758 to +765
const { destinationEntityId, id, name } = action.payload;
let actionObject: Action = yield select(getAction, id);

const { parentEntityId, parentEntityKey } =
resolveParentEntityMetadata(actionObject);

if (!parentEntityId || !parentEntityKey) return;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential undefined parentEntityId or parentEntityKey

In copyActionSaga, if parentEntityId or parentEntityKey are undefined, the function returns early. Ensure that this behavior is expected and that any necessary error handling or user feedback is in place.

Comment on lines +1075 to +1078
const { parentEntityId } = resolveParentEntityMetadata(actionPayload.payload);

if (!parentEntityId) return;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure parentEntityId is defined before proceeding

In handleMoveOrCopySaga, if parentEntityId is undefined, the function returns early. Verify that this is the intended behavior and handle any necessary error messaging or fallback logic.

Comment on lines +1079 to +1082
const baseParentEntityId: string = yield select(
convertToBaseParentEntityIdSelector,
parentEntityId,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use baseParentEntityId safely

You're selecting baseParentEntityId using parentEntityId. Since parentEntityId might be undefined (as checked earlier), ensure that baseParentEntityId is valid before using it to avoid potential errors.

@ayushpahwa ayushpahwa merged commit 0b93768 into release Oct 24, 2024
86 checks passed
@ayushpahwa ayushpahwa deleted the feat/query-duplication-wf branch October 24, 2024 08:31
github-actions bot pushed a commit to Zeral-Zhang/appsmith that referenced this pull request Nov 20, 2024
## Description
This PR refactors the action duplication saga and action calls to remove
dependency on pageID. As far as CE code is concerned, this PR doesn't
change any functionality for the end user. Those changes are done for
workflows editor in EE.


Fixes appsmithorg#36886

## Automation

/test all

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/11462274307>
> Commit: 04dfbfb
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=11462274307&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 22 Oct 2024 16:21:32 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced a new hook, `useHandleDuplicateClick`, enhancing action
duplication functionality.
- Added a new interface and function for generating destination ID
information.

- **Bug Fixes**
- Updated action request structure to use `destinationEntityId` for
consistency across components.

- **Documentation**
	- Enhanced success message flexibility for action copy notifications.

- **Tests**
- Added unit tests for the `ActionEntityContextMenu` component to ensure
proper functionality and rendering.

- **Refactor**
- Improved context menu handling based on entity types for better user
experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Required label for CI skip-changelog Adding this label to a PR prevents it from being listed in the changelog Workflows Pod Issues that the workflows team owns Workflows Product Issues related to the workflows product
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Allow queries to be duplicated in workflow editor
3 participants