From 579cb7d0a62ab49e18394387fcf675fb2eaed7a3 Mon Sep 17 00:00:00 2001 From: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:16:42 +0530 Subject: [PATCH] feat: Updated GraphQL form UI (#36728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR has following new features and fixes 1. Feat: Update GraphQL to use form control dynamic text field instead of custom implementation. 2. Feat: Added full width support for section component in action form. 3. Fix: Rest API headers not scrollable if there are more number of items. EE PR: https://github.com/appsmithorg/appsmith-ee/pull/5297 Fixes #35494 Fixes #36410 Fixes #36499 ## Automation /ok-to-test tags="@tag.All" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 14b3e0020d312463eab177ace625a8ca705b4629 > Cypress dashboard. > Tags: `@tag.All` > Spec: >
Wed, 09 Oct 2024 05:42:42 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced a streamlined form-based design for the `PostBodyData` component, enhancing user interaction with dynamic text fields for GraphQL queries and variables. - Added a new styled component, `MainContainer`, to improve layout responsiveness in the `CommonEditorForm`. - Enhanced the `Section` component with an optional `isFullWidth` property for greater configurability. - **Bug Fixes** - Adjusted the `LoadingContainer` height dynamically to enhance UI responsiveness. - **Style** - Updated styles for the `Section` component to support full-width expansion when applicable. - **Removed Features** - Deprecated the `QueryEditor` and `VariableEditor` components, simplifying the editor interface. --- .../components/GraphQLEditor/PostBodyData.tsx | 148 ++++++++---------- .../Editor/APIEditor/CommonEditorForm.tsx | 1 + .../src/pages/Editor/APIEditor/Editor.tsx | 3 +- .../Editor/APIEditor/GraphQL/QueryEditor.tsx | 67 -------- .../APIEditor/GraphQL/VariableEditor.tsx | 77 --------- .../pages/Editor/ActionForm/Section/index.tsx | 3 + .../ActionForm/Section/styles.module.css | 4 + 7 files changed, 74 insertions(+), 229 deletions(-) delete mode 100644 app/client/src/pages/Editor/APIEditor/GraphQL/QueryEditor.tsx delete mode 100644 app/client/src/pages/Editor/APIEditor/GraphQL/VariableEditor.tsx diff --git a/app/client/src/PluginActionEditor/components/PluginActionForm/components/GraphQLEditor/PostBodyData.tsx b/app/client/src/PluginActionEditor/components/PluginActionForm/components/GraphQLEditor/PostBodyData.tsx index f897d38246e9..211042452700 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionForm/components/GraphQLEditor/PostBodyData.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionForm/components/GraphQLEditor/PostBodyData.tsx @@ -1,107 +1,87 @@ -import React, { useCallback, useRef } from "react"; +import React from "react"; import styled from "styled-components"; -import QueryEditor from "pages/Editor/APIEditor/GraphQL/QueryEditor"; -import VariableEditor from "pages/Editor/APIEditor/GraphQL/VariableEditor"; -import useHorizontalResize from "utils/hooks/useHorizontalResize"; -import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; -import classNames from "classnames"; -import { tailwindLayers } from "constants/Layers"; - -const ResizableDiv = styled.div` - display: flex; - height: 100%; - flex-shrink: 0; -`; +import { + CodeEditorBorder, + EditorModes, + EditorSize, + EditorTheme, + TabBehaviour, +} from "components/editorComponents/CodeEditor/EditorConfig"; +import DynamicTextField from "components/editorComponents/form/fields/DynamicTextField"; +import { Section, Zone } from "pages/Editor/ActionForm"; +import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; +import FormLabel from "components/editorComponents/FormLabel"; const PostBodyContainer = styled.div` - display: flex; - height: 100%; - overflow: hidden; &&&& .CodeMirror { - height: 100%; - border-top: 1px solid var(--ads-v2-color-border); - border-bottom: 1px solid var(--ads-v2-color-border); - border-radius: 0; - padding: 0; - } - & .CodeMirror-scroll { - margin: 0px; - padding: 0px; - overflow: auto !important; + height: auto; + min-height: 250px; } `; -const ResizerHandler = styled.div<{ resizing: boolean }>` - width: 6px; - height: 100%; - margin-left: 2px; - border-right: 1px solid var(--ads-v2-color-border); - background: ${(props) => - props.resizing ? "var(--ads-v2-color-border)" : "transparent"}; - &:hover { - background: var(--ads-v2-color-border); - border-color: transparent; +const StyledFormLabel = styled(FormLabel)` + && { + margin-bottom: var(--ads-v2-spaces-2); + padding: 0; } `; -const DEFAULT_GRAPHQL_VARIABLE_WIDTH = 300; - interface Props { actionName: string; } +const EXPECTED_VARIABLE = { + type: "object", + example: + '{\n "name":"{{ inputName.property }}",\n "preference":"{{ dropdownName.property }}"\n}', + autocompleteDataType: AutocompleteDataType.OBJECT, +}; + function PostBodyData(props: Props) { const { actionName } = props; const theme = EditorTheme.LIGHT; - const resizeableRef = useRef(null); - const [variableEditorWidth, setVariableEditorWidth] = React.useState( - DEFAULT_GRAPHQL_VARIABLE_WIDTH, - ); - /** - * Variable Editor's resizeable handler for the changing of width - */ - const onVariableEditorWidthChange = useCallback((newWidth) => { - setVariableEditorWidth(newWidth); - }, []); - - const { onMouseDown, onMouseUp, onTouchStart, resizing } = - useHorizontalResize( - resizeableRef, - onVariableEditorWidthChange, - undefined, - true, - ); return ( - -
- -
- - - +
+ +
+ Query + +
+
+ +
+ Query variables + +
+
+
); } diff --git a/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx b/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx index 71baf3d547d4..80a1748ad0c7 100644 --- a/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx +++ b/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx @@ -111,6 +111,7 @@ const Wrapper = styled.div` flex-direction: row; height: 100%; position: relative; + overflow: hidden; `; const MainContainer = styled.div` diff --git a/app/client/src/pages/Editor/APIEditor/Editor.tsx b/app/client/src/pages/Editor/APIEditor/Editor.tsx index 5ce681b23e05..1e6fab13010d 100644 --- a/app/client/src/pages/Editor/APIEditor/Editor.tsx +++ b/app/client/src/pages/Editor/APIEditor/Editor.tsx @@ -229,9 +229,10 @@ class ApiEditor extends React.Component { const formStyles: CSSProperties = { position: "relative", - height: "100%", display: "flex", flexDirection: "column", + flexGrow: "1", + overflow: "auto", }; // TODO: Fix this the next time the file is edited diff --git a/app/client/src/pages/Editor/APIEditor/GraphQL/QueryEditor.tsx b/app/client/src/pages/Editor/APIEditor/GraphQL/QueryEditor.tsx deleted file mode 100644 index 53948e1520b4..000000000000 --- a/app/client/src/pages/Editor/APIEditor/GraphQL/QueryEditor.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from "react"; -import { Field } from "redux-form"; -// // Codemirror GraphQL plugins -import "codemirror-graphql/hint"; -import "codemirror-graphql/info"; -import "codemirror-graphql/jump"; -import "codemirror-graphql/mode"; - -import QueryWrapper from "./QueryWrapperWithCSS"; -import type { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; -import { - CodeEditorBorder, - EditorModes, - EditorSize, - TabBehaviour, -} from "components/editorComponents/CodeEditor/EditorConfig"; -import styled from "styled-components"; -import { Text, TextType } from "@appsmith/ads-old"; -import LazyCodeEditor from "components/editorComponents/LazyCodeEditor"; - -const QueryHeader = styled(Text)` - background: var(--ads-v2-color-bg-subtle); - padding: 8px 16px; -`; - -interface QueryProps { - // Path to store the value in the actual data object - dataTreePath: string; - // Height for the editor - height: string; - // Name of the field of the form - name: string; - // Theme to be used in CodeEditor - theme: EditorTheme; -} - -/** - * Query Editor is for writing Graphql query using the Codemirror Editor which we use - * @param props Props that are required by the CodeEditor to render the query editor - * @returns Component with Editor - */ -function QueryEditor(props: QueryProps) { - const editorProps = { - mode: EditorModes.GRAPHQL_WITH_BINDING, - tabBehaviour: TabBehaviour.INDENT, - size: EditorSize.EXTENDED, - showLineNumbers: true, - }; - - return ( - - - Query - - - - ); -} - -export default QueryEditor; diff --git a/app/client/src/pages/Editor/APIEditor/GraphQL/VariableEditor.tsx b/app/client/src/pages/Editor/APIEditor/GraphQL/VariableEditor.tsx deleted file mode 100644 index 89a3d3b96d34..000000000000 --- a/app/client/src/pages/Editor/APIEditor/GraphQL/VariableEditor.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from "react"; -import type { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; -import { - CodeEditorBorder, - EditorModes, - EditorSize, - TabBehaviour, -} from "components/editorComponents/CodeEditor/EditorConfig"; -import styled from "styled-components"; -import { Text, TextType } from "@appsmith/ads-old"; -import DynamicTextField from "components/editorComponents/form/fields/DynamicTextField"; -import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; - -const VariableWrapper = styled.div` - display: flex; - flex-direction: column; - width: 100%; - flex-shrink: 0; - &&&&& .CodeMirror { - border: 0px; - } - &&& .CodeMirror-gutters { - background: var(--ads-v2-color-bg-subtle); - } -`; - -const VariableHeader = styled(Text)` - background: var(--ads-v2-color-bg-subtle); - padding: 8px 16px; -`; - -const EXPECTED_VARIABLE = { - type: "object", - example: - '{\n "name":"{{ inputName.property }}",\n "preference":"{{ dropdownName.property }}"\n}', - autocompleteDataType: AutocompleteDataType.OBJECT, -}; - -interface VariableProps { - // Name of the action to define the path to the config property - actionName: string; - // Theme to be used in CodeEditor - theme: EditorTheme; -} - -/** - * Variable Editor is for writing Graphql variables using the Codemirror Editor which we use for JSON - * @param props Props that are required by the CodeEditor to render the variable editor - * @returns Component with Editor - */ -function VariableEditor(props: VariableProps) { - return ( - - - Query variables - - - - ); -} - -export default VariableEditor; diff --git a/app/client/src/pages/Editor/ActionForm/Section/index.tsx b/app/client/src/pages/Editor/ActionForm/Section/index.tsx index 937ad0b631d5..7b664e119607 100644 --- a/app/client/src/pages/Editor/ActionForm/Section/index.tsx +++ b/app/client/src/pages/Editor/ActionForm/Section/index.tsx @@ -5,11 +5,13 @@ import styles from "./styles.module.css"; interface SectionProps extends React.HTMLAttributes { children: React.ReactNode; isStandalone?: boolean; + isFullWidth?: boolean; } const Section: React.FC = ({ children, className, + isFullWidth = false, isStandalone = false, ...props }) => { @@ -18,6 +20,7 @@ const Section: React.FC = ({ return (
diff --git a/app/client/src/pages/Editor/ActionForm/Section/styles.module.css b/app/client/src/pages/Editor/ActionForm/Section/styles.module.css index e3d2a2d2f309..fb03da7ffbd3 100644 --- a/app/client/src/pages/Editor/ActionForm/Section/styles.module.css +++ b/app/client/src/pages/Editor/ActionForm/Section/styles.module.css @@ -13,4 +13,8 @@ &[data-standalone="false"]:not(:last-child) { border-bottom: 1px solid var(--ads-v2-color-border); } + + &[data-fullwidth="true"] { + max-width: none; + } }