From d48ac4fd81a98fa4c9dadcd8a9509321369e82a3 Mon Sep 17 00:00:00 2001 From: ashit-rath Date: Tue, 17 Oct 2023 10:53:55 +0530 Subject: [PATCH] chore: action editors refactor (#27972) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description The aim of this PR is to make the editors reusable in the Module editor. Changes 1. A wrapper is introduced for API, Query and Curl editors which passes differentiating functions and make the form editors agnostic of pageId and applicationId 2. In order to pass down function, react contexts are added to avoid prop drilling #### PR fixes following issue(s) Fixes #26160 #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change - Chore (housekeeping or task changes that don't impact user perception) ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- app/client/src/actions/queryPaneActions.ts | 18 +- .../src/components/common/BackToCanvas.tsx | 46 ++ .../editorComponents/ActionNameEditor.tsx | 17 +- .../ActionRightPane/index.tsx | 44 +- .../Editor/APIEditor/ApiEditorContext.tsx | 65 +++ .../pages/Editor/APIEditor/ApiRightPane.tsx | 1 + .../Editor/APIEditor/CommonEditorForm.tsx | 34 +- .../Editor/APIEditor/CurlImportEditor.tsx | 41 ++ .../pages/Editor/APIEditor/CurlImportForm.tsx | 67 +-- .../src/pages/Editor/APIEditor/Editor.tsx | 276 +++++++++++ .../APIEditor/GraphQL/GraphQLEditorForm.tsx | 6 +- .../Editor/APIEditor/RapidApiEditorForm.tsx | 7 +- .../pages/Editor/APIEditor/RestAPIForm.tsx | 5 +- .../src/pages/Editor/APIEditor/index.tsx | 407 +++++----------- .../src/pages/Editor/QueryEditor/Editor.tsx | 352 ++++++++++++++ .../Editor/QueryEditor/EditorJSONtoForm.tsx | 37 +- .../Editor/QueryEditor/QueryEditorContext.tsx | 64 +++ .../src/pages/Editor/QueryEditor/index.tsx | 453 ++++-------------- app/client/src/pages/Editor/routes.tsx | 4 +- app/client/src/sagas/QueryPaneSagas.ts | 30 +- app/client/src/selectors/ui.tsx | 3 + 21 files changed, 1166 insertions(+), 811 deletions(-) create mode 100644 app/client/src/components/common/BackToCanvas.tsx create mode 100644 app/client/src/pages/Editor/APIEditor/ApiEditorContext.tsx create mode 100644 app/client/src/pages/Editor/APIEditor/CurlImportEditor.tsx create mode 100644 app/client/src/pages/Editor/APIEditor/Editor.tsx create mode 100644 app/client/src/pages/Editor/QueryEditor/Editor.tsx create mode 100644 app/client/src/pages/Editor/QueryEditor/QueryEditorContext.tsx diff --git a/app/client/src/actions/queryPaneActions.ts b/app/client/src/actions/queryPaneActions.ts index c2288e17ee..7074964120 100644 --- a/app/client/src/actions/queryPaneActions.ts +++ b/app/client/src/actions/queryPaneActions.ts @@ -2,18 +2,20 @@ import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import type { Action } from "entities/Action"; -export const changeQuery = ( - id: string, - newQuery?: boolean, - action?: Action, -): ReduxAction<{ +export interface ChangeQueryPayload { id: string; + packageId?: string; + applicationId?: string; + pageId?: string; + moduleId?: string; newQuery?: boolean; - action?: any; -}> => { + action?: Action; +} + +export const changeQuery = (payload: ChangeQueryPayload) => { return { type: ReduxActionTypes.QUERY_PANE_CHANGE, - payload: { id, newQuery, action }, + payload, }; }; diff --git a/app/client/src/components/common/BackToCanvas.tsx b/app/client/src/components/common/BackToCanvas.tsx new file mode 100644 index 0000000000..fcf0df3a89 --- /dev/null +++ b/app/client/src/components/common/BackToCanvas.tsx @@ -0,0 +1,46 @@ +import React, { useCallback, useContext } from "react"; +import styled from "styled-components"; +import { Link } from "design-system"; + +import history from "utils/history"; +import WalkthroughContext from "components/featureWalkthrough/walkthroughContext"; +import { BACK_TO_CANVAS, createMessage } from "@appsmith/constants/messages"; +import { builderURL } from "@appsmith/RouteBuilder"; + +const BackToCanvasLink = styled(Link)` + margin-left: ${(props) => props.theme.spaces[1] + 1}px; + margin-top: ${(props) => props.theme.spaces[11]}px; + margin-bottom: ${(props) => props.theme.spaces[11]}px; +`; + +interface BackToCanvasProps { + pageId: string; +} + +function BackToCanvas({ pageId }: BackToCanvasProps) { + const { isOpened: isWalkthroughOpened, popFeature } = + useContext(WalkthroughContext) || {}; + + const handleCloseWalkthrough = useCallback(() => { + if (isWalkthroughOpened && popFeature) { + popFeature(); + } + }, [isWalkthroughOpened, popFeature]); + + return ( + { + history.push(builderURL({ pageId })); + + handleCloseWalkthrough(); + }} + startIcon="arrow-left-line" + > + {createMessage(BACK_TO_CANVAS)} + + ); +} + +export default BackToCanvas; diff --git a/app/client/src/components/editorComponents/ActionNameEditor.tsx b/app/client/src/components/editorComponents/ActionNameEditor.tsx index 88e301911a..b666874452 100644 --- a/app/client/src/components/editorComponents/ActionNameEditor.tsx +++ b/app/client/src/components/editorComponents/ActionNameEditor.tsx @@ -21,6 +21,7 @@ import { createMessage, } from "@appsmith/constants/messages"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; +import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; const ApiNameWrapper = styled.div<{ page?: string }>` min-width: 50%; @@ -58,6 +59,11 @@ const ApiIconBox = styled.div` margin-right: 8px; flex-shrink: 0; `; + +interface SaveActionNameParams { + id: string; + name: string; +} interface ActionNameEditorProps { /* This prop checks if page is API Pane or Query Pane or Curl Pane @@ -67,6 +73,9 @@ interface ActionNameEditorProps { */ page?: string; disabled?: boolean; + saveActionName?: ( + params: SaveActionNameParams, + ) => ReduxAction; } function ActionNameEditor(props: ActionNameEditorProps) { @@ -84,7 +93,13 @@ function ActionNameEditor(props: ActionNameEditorProps) { {({ forceUpdate, diff --git a/app/client/src/components/editorComponents/ActionRightPane/index.tsx b/app/client/src/components/editorComponents/ActionRightPane/index.tsx index 948c4d0398..4bdcfda2ac 100644 --- a/app/client/src/components/editorComponents/ActionRightPane/index.tsx +++ b/app/client/src/components/editorComponents/ActionRightPane/index.tsx @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useMemo, useRef, useState } from "react"; import styled from "styled-components"; import { Collapse, Classes as BPClasses } from "@blueprintjs/core"; import { Classes, getTypographyByKey } from "design-system-old"; -import { Divider, Icon, Link, Text } from "design-system"; +import { Divider, Icon, Text } from "design-system"; import SuggestedWidgets from "./SuggestedWidgets"; import type { ReactNode, MutableRefObject } from "react"; import { useParams } from "react-router"; @@ -11,7 +11,6 @@ import { getWidgets } from "sagas/selectors"; import type { AppState } from "@appsmith/reducers"; import { getDependenciesFromInverseDependencies } from "../Debugger/helpers"; import { - BACK_TO_CANVAS, BINDINGS_DISABLED_TOOLTIP, BINDING_SECTION_LABEL, createMessage, @@ -23,11 +22,7 @@ import type { SuggestedWidget, SuggestedWidget as SuggestedWidgetsType, } from "api/ActionAPI"; -import { - getCurrentPageId, - getPagePermissions, -} from "selectors/editorSelectors"; -import { builderURL } from "@appsmith/RouteBuilder"; +import { getPagePermissions } from "selectors/editorSelectors"; import DatasourceStructureHeader from "pages/Editor/Explorer/Datasources/DatasourceStructureHeader"; import { DatasourceStructureContainer as DataStructureList, @@ -55,7 +50,6 @@ import { Tooltip } from "design-system"; import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { FEATURE_WALKTHROUGH_KEYS } from "constants/WalkthroughConstants"; import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; -import history from "utils/history"; import { SignpostingWalkthroughConfig } from "pages/Editor/FirstTimeUserOnboarding/Utils"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; @@ -113,12 +107,6 @@ const SideBar = styled.div` } `; -const BackToCanvasLink = styled(Link)` - margin-left: ${(props) => props.theme.spaces[1] + 1}px; - margin-top: ${(props) => props.theme.spaces[11]}px; - margin-bottom: ${(props) => props.theme.spaces[11]}px; -`; - const Label = styled.span` cursor: pointer; `; @@ -291,6 +279,7 @@ export function useEntityDependencies(actionName: string) { function ActionSidebar({ actionName, + actionRightPaneBackLink, context, datasourceId, hasConnections, @@ -305,16 +294,12 @@ function ActionSidebar({ datasourceId: string; pluginId: string; context: DatasourceStructureContext; + actionRightPaneBackLink: React.ReactNode; }) { const dispatch = useDispatch(); const widgets = useSelector(getWidgets); - const pageId = useSelector(getCurrentPageId); const user = useSelector(getCurrentUser); - const { - isOpened: isWalkthroughOpened, - popFeature, - pushFeature, - } = useContext(WalkthroughContext) || {}; + const { pushFeature } = useContext(WalkthroughContext) || {}; const schemaRef = useRef(null); const params = useParams<{ pageId: string; @@ -444,26 +429,9 @@ function ActionSidebar({ return {createMessage(NO_CONNECTIONS)}; } - const handleCloseWalkthrough = () => { - if (isWalkthroughOpened && popFeature) { - popFeature(); - } - }; - return ( - { - history.push(builderURL({ pageId })); - - handleCloseWalkthrough(); - }} - startIcon="arrow-left-line" - > - {createMessage(BACK_TO_CANVAS)} - + {actionRightPaneBackLink} {showSchema && ( void; + handleRunClick: (paginationField?: PaginationField) => void; + actionRightPaneBackLink?: React.ReactNode; + settingsConfig: any; + saveActionName?: ( + params: SaveActionNameParams, + ) => ReduxAction; + closeEditorLink?: React.ReactNode; +} + +type ApiEditorContextProviderProps = + React.PropsWithChildren; + +export const ApiEditorContext = createContext( + {} as ApiEditorContextContextProps, +); + +export function ApiEditorContextProvider({ + actionRightPaneBackLink, + children, + closeEditorLink, + handleDeleteClick, + handleRunClick, + moreActionsMenu, + saveActionName, + settingsConfig, +}: ApiEditorContextProviderProps) { + const value = useMemo( + () => ({ + actionRightPaneBackLink, + closeEditorLink, + handleDeleteClick, + handleRunClick, + moreActionsMenu, + saveActionName, + settingsConfig, + }), + [ + actionRightPaneBackLink, + closeEditorLink, + handleDeleteClick, + handleRunClick, + moreActionsMenu, + saveActionName, + settingsConfig, + ], + ); + + return ( + + {children} + + ); +} diff --git a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx index 29baf5b6de..2b4ee57f39 100644 --- a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx +++ b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx @@ -310,6 +310,7 @@ function ApiRightPane(props: any) { action.id === params.apiId || action.id === params.queryId, ); - const { pageId } = useParams(); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); const isChangePermitted = getHasManageActionPermission( isFeatureEnabled, @@ -542,10 +542,6 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) { isFeatureEnabled, currentActionConfig?.userPermissions, ); - const isDeletePermitted = getHasDeleteActionPermission( - isFeatureEnabled, - currentActionConfig?.userPermissions, - ); const plugin = useSelector((state: AppState) => getPlugin(state, pluginId ?? ""), @@ -577,22 +573,19 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) { return ( - + {closeEditorLink}
- + - + {moreActionsMenu}