From dd5a6d6792a1fc1385a2fc38ba44212ec076c419 Mon Sep 17 00:00:00 2001 From: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:43:27 +0530 Subject: [PATCH 01/19] feat: Added focus ring for focus visible (#37700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR adds focus ring for CTA's in the platform. Fixes #37699 ## Automation /ok-to-test tags="@tag.Sanity" ### :mag: Cypress test results > [!TIP] > 🟒 🟒 🟒 All cypress tests have passed! πŸŽ‰ πŸŽ‰ πŸŽ‰ > Workflow run: > Commit: 25970876103fc1ea3f9feeba62f3be10b0783638 > Cypress dashboard. > Tags: `@tag.Sanity` > Spec: >
Mon, 13 Jan 2025 08:19:28 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No ## Summary by CodeRabbit - **New Features** - Enhanced focus state styling for the select component, improving visibility when active. - Updated focus management for buttons, inputs, and various components to utilize `:focus-visible`, enhancing accessibility. - Refined keyboard navigation and interaction logic for the color picker component. - Introduced new props for conditional focus styling in the editor and button components. - Added support for AI assistance features in the code editor. - Improved focus ring visibility in the segmented control and switch components. - **Bug Fixes** - Improved accessibility and visual clarity of focus outlines across the application. - **Chores** - Removed outdated focus outline rules, allowing for a more streamlined styling approach. --- .../ads-old/src/SearchComponent/index.tsx | 7 +++--- .../ads/src/Button/Button.styles.tsx | 16 +++++++++----- .../design-system/ads/src/Button/Button.tsx | 18 ++++++++++----- .../ads/src/Input/Input.styles.tsx | 22 +++++++++---------- .../design-system/ads/src/Input/Input.tsx | 16 +++++++------- .../ads/src/Link/Link.styles.tsx | 4 ++-- .../SegmentedControl.styles.tsx | 4 ++-- .../design-system/ads/src/Select/styles.css | 12 +++++++--- .../ads/src/Switch/Switch.styles.tsx | 5 +++-- .../design-system/ads/src/Tab/Tab.styles.tsx | 4 ++-- .../ads/src/Text/Text.styles.tsx | 7 +++++- .../ads/src/__theme__/default/index.css | 17 +++++++++----- .../editorComponents/CodeEditor/index.tsx | 1 + .../CodeEditor/styledComponents.ts | 21 +++++++++++++----- .../ColorPickerComponentV2.tsx | 5 ++--- .../propertyControls/IconSelectControl.tsx | 4 ++-- .../propertyControls/IconSelectControlV2.tsx | 4 ++-- app/client/src/index.css | 17 -------------- 18 files changed, 103 insertions(+), 81 deletions(-) diff --git a/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx b/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx index ab51942ff46b..b8f211c1531f 100644 --- a/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx +++ b/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx @@ -63,10 +63,11 @@ const SearchInputWrapper = styled(InputGroup)<{ text-overflow: ellipsis; width: 100%; } + input:focus { - border: 1.2px solid var(--ads-old-color-fern-green); - box-sizing: border-box; - width: 100%; + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); } input:active { diff --git a/app/client/packages/design-system/ads/src/Button/Button.styles.tsx b/app/client/packages/design-system/ads/src/Button/Button.styles.tsx index 1fd71a2ca84f..e6d5e768345d 100644 --- a/app/client/packages/design-system/ads/src/Button/Button.styles.tsx +++ b/app/client/packages/design-system/ads/src/Button/Button.styles.tsx @@ -210,6 +210,7 @@ export const StyledButton = styled.button<{ UNSAFE_width?: string; disabled?: boolean; isIconButton?: boolean; + isFocusVisible?: boolean; }>` ${Variables} /* Kind style */ @@ -269,11 +270,14 @@ export const StyledButton = styled.button<{ } } - /* Focus styles */ - &:focus-visible { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } + ${({ isFocusVisible }) => + isFocusVisible && + css` + :focus-visible { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + } + `} } `; diff --git a/app/client/packages/design-system/ads/src/Button/Button.tsx b/app/client/packages/design-system/ads/src/Button/Button.tsx index ca98873225e4..4fe30a4265b6 100644 --- a/app/client/packages/design-system/ads/src/Button/Button.tsx +++ b/app/client/packages/design-system/ads/src/Button/Button.tsx @@ -1,5 +1,6 @@ import React, { forwardRef } from "react"; import clsx from "classnames"; +import { useFocusRing } from "@react-aria/focus"; import { StyledButton, ButtonContent } from "./Button.styles"; import type { ButtonProps } from "./Button.types"; @@ -16,6 +17,11 @@ import { } from "./Button.constants"; import { Spinner } from "../Spinner"; +// Add this before the Button component definition +const SPINNER_ICON_PROPS = { + className: ButtonLoadingIconClassName, +}; + /** * TODO: * - if both left and right icon is used, disregard left icon and print a warning in the console. @@ -37,21 +43,25 @@ const Button = forwardRef( ...rest } = props; - // disable button when loading - rest.onClick = + // Replace the direct mutation of rest.onClick with this + const handleClick = props.isLoading || props.isDisabled ? undefined : props.onClick; const buttonRef = useDOMRef(ref); + const { focusProps, isFocusVisible } = useFocusRing(); return ( ( {isLoading === true && ( )} diff --git a/app/client/packages/design-system/ads/src/Input/Input.styles.tsx b/app/client/packages/design-system/ads/src/Input/Input.styles.tsx index 5c2bf55e5f16..2b33df832085 100644 --- a/app/client/packages/design-system/ads/src/Input/Input.styles.tsx +++ b/app/client/packages/design-system/ads/src/Input/Input.styles.tsx @@ -164,7 +164,7 @@ export const StyledInput = styled.input<{ renderer === "input" && css` padding-left: calc((var(--input-padding-x) * 2) + var(--icon-size) - 1px); - `}; + `} /* adjust padding end according to icon present or not */ ${({ hasEndIcon, renderer }) => @@ -174,20 +174,13 @@ export const StyledInput = styled.input<{ padding-right: calc( (var(--input-padding-x) * 2) + var(--icon-size) - 1px ); - `}; - - &:focus:enabled:not(:read-only) { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } + `} &:hover:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-hover-border); } - &:active:enabled:not(:read-only), - &:focus:enabled:not(:read-only) { + &:active:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-active-border); } @@ -203,11 +196,16 @@ export const StyledInput = styled.input<{ --input-color-border: var(--ads-v2-colors-control-field-error-border); } - &:active:enabled:not(:read-only), - &:focus:enabled:not(:read-only) { + &:active:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-error-border); } } + + &:focus { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + } `; export const Description = styled(Text)` diff --git a/app/client/packages/design-system/ads/src/Input/Input.tsx b/app/client/packages/design-system/ads/src/Input/Input.tsx index c196c17e1655..c3c57afda23f 100644 --- a/app/client/packages/design-system/ads/src/Input/Input.tsx +++ b/app/client/packages/design-system/ads/src/Input/Input.tsx @@ -1,5 +1,4 @@ -import React, { forwardRef } from "react"; -import { useFocusRing } from "@react-aria/focus"; +import React, { forwardRef, useCallback } from "react"; import { useTextField } from "@react-aria/textfield"; import clsx from "classnames"; @@ -55,7 +54,7 @@ const Input = forwardRef( const { descriptionProps, errorMessageProps, inputProps, labelProps } = // @ts-expect-error fix this the next time the file is edited useTextField(props, inputRef); - const { focusProps, isFocusVisible } = useFocusRing(); + const { className: startIconClassName, onClick: startIconOnClick, @@ -67,9 +66,12 @@ const Input = forwardRef( ...restOfEndIconProps } = endIconProps || {}; - const handleOnChange = (event: React.ChangeEvent) => { - onChange?.(event.target.value); - }; + const handleOnChange = useCallback( + (event: React.ChangeEvent) => { + onChange?.(event.target.value); + }, + [onChange], + ); isValid = isValid === undefined ? !errorMessage : isValid; @@ -116,7 +118,6 @@ const Input = forwardRef( ( hasEndIcon={!!endIcon} hasStartIcon={!!startIcon} inputSize={size} - isFocusVisible={isFocusVisible} onChange={handleOnChange} readOnly={isReadOnly} ref={inputRef} diff --git a/app/client/packages/design-system/ads/src/Link/Link.styles.tsx b/app/client/packages/design-system/ads/src/Link/Link.styles.tsx index 357316fd4d7b..8c853d0e4ba1 100644 --- a/app/client/packages/design-system/ads/src/Link/Link.styles.tsx +++ b/app/client/packages/design-system/ads/src/Link/Link.styles.tsx @@ -91,8 +91,8 @@ export const Styles = css<{ kind?: LinkKind }>` :focus-visible { outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; border-radius: var(--ads-v2-border-radius); } `; diff --git a/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx b/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx index df71f94da913..ce6db61c5535 100644 --- a/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx +++ b/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx @@ -67,8 +67,8 @@ export const StyledControlContainer = styled.div` &:focus-visible { outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } &[data-disabled="true"] { diff --git a/app/client/packages/design-system/ads/src/Select/styles.css b/app/client/packages/design-system/ads/src/Select/styles.css index cc67992917a6..5df37c481ce4 100644 --- a/app/client/packages/design-system/ads/src/Select/styles.css +++ b/app/client/packages/design-system/ads/src/Select/styles.css @@ -1,7 +1,9 @@ .ads-v2-select { --select-color-border: var(--ads-v2-colors-control-field-default-border); - --select-padding-x: var(--ads-v2-spaces-2); /* padding left and right */ - --select-padding-y: var(--ads-v2-spaces-2); /* padding top and bottom */ + --select-padding-x: var(--ads-v2-spaces-2); + /* padding left and right */ + --select-padding-y: var(--ads-v2-spaces-2); + /* padding top and bottom */ --select-font-size: var(--ads-v2-font-size-2); --select-height: 24px; --select-search-input-padding-right: 0; @@ -51,7 +53,6 @@ .ads-v2-select.rc-select-focused { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); outline-offset: var(--ads-v2-offset-outline); - --select-color-border: var(--ads-v2-colors-control-field-active-border); } /* Error */ @@ -87,6 +88,7 @@ /* padding x + icon size + gap */ --select-search-input-padding-right: calc(var(--select-padding-x) + 16px); } + .ads-v2-select.rc-select-allow-clear.rc-select-show-arrow.rc-select-selection-search-input, .ads-v2-select.rc-select-allow-clear.rc-select-show-arrow .rc-select-selection-overflow { @@ -113,6 +115,10 @@ overflow: hidden; } +.ads-v2-select.rc-select-focused > .rc-select-selector { + border-color: transparent; +} + /* Placeholder */ .ads-v2-select > .rc-select-selector > .rc-select-selection-placeholder, .ads-v2-select > .rc-select-selector > .rc-select-selection-item { diff --git a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx index 2b0358ffeee2..f4459720fc52 100644 --- a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx +++ b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx @@ -72,8 +72,9 @@ export const StyledSwitchInput = styled.input<{ ${({ isFocusVisible }) => isFocusVisible && ` - outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; `} &:hover { diff --git a/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx b/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx index 082c272ceba1..1abc54866a9b 100644 --- a/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx +++ b/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx @@ -88,7 +88,7 @@ export const StyledTab = styled(RadixTabs.TabsTrigger)` &:focus-visible { --tab-color: var(--ads-v2-colors-content-label-default-fg); outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } `; diff --git a/app/client/packages/design-system/ads/src/Text/Text.styles.tsx b/app/client/packages/design-system/ads/src/Text/Text.styles.tsx index 55f278fa7b1d..3610ce324ecf 100644 --- a/app/client/packages/design-system/ads/src/Text/Text.styles.tsx +++ b/app/client/packages/design-system/ads/src/Text/Text.styles.tsx @@ -201,8 +201,13 @@ export const StyledEditableInput = styled.input` border-color: var(--ads-v2-colors-control-field-hover-border); } - &:focus, &:active { border-color: var(--ads-v2-colors-control-field-active-border); } + + &:focus-visible { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); + } `; diff --git a/app/client/packages/design-system/ads/src/__theme__/default/index.css b/app/client/packages/design-system/ads/src/__theme__/default/index.css index ad6c149f68c3..8ade0c331b89 100644 --- a/app/client/packages/design-system/ads/src/__theme__/default/index.css +++ b/app/client/packages/design-system/ads/src/__theme__/default/index.css @@ -239,9 +239,9 @@ /* --ads-v2-color-outline: var(--ads-v2-color-blue-300); --ads-v2-border-width-outline: 2px; */ /* TODO: fix focus issue across the platform */ - --ads-v2-color-outline: transparent; - --ads-v2-border-width-outline: 0; - --ads-v2-offset-outline: 0; + --ads-v2-color-outline: var(--ads-v2-color-blue-300); + --ads-v2-border-width-outline: 2px; + --ads-v2-offset-outline: -2px; /** * ===========================================* @@ -251,17 +251,22 @@ --ads-v2-opacity-disabled: 0.6; } +:focus { + outline: none !important; +} + /* react-aria useFocusRing helper class*/ .ads-v2-focus-ring { - outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } /* Placeholder color */ ::placeholder { /* This needs to be important to override the placeholder color on main repo */ color: var(--ads-v2-colors-control-placeholder-default-fg) !important; - opacity: 1; /* Firefox */ + opacity: 1; + /* Firefox */ } :-ms-input-placeholder { diff --git a/app/client/src/components/editorComponents/CodeEditor/index.tsx b/app/client/src/components/editorComponents/CodeEditor/index.tsx index 8c9027dc647e..21610927e3c2 100644 --- a/app/client/src/components/editorComponents/CodeEditor/index.tsx +++ b/app/client/src/components/editorComponents/CodeEditor/index.tsx @@ -1794,6 +1794,7 @@ class CodeEditor extends Component { onMouseOver={this.handleMouseMove} ref={this.editorWrapperRef} removeHoverAndFocusStyle={this.props?.removeHoverAndFocusStyle} + showFocusVisible={!this.props.isJSObject} size={size} > {this.state.peekOverlayProps && ( diff --git a/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts b/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts index 5c4cd413679a..c26b3eec794e 100644 --- a/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts +++ b/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts @@ -54,6 +54,7 @@ export const EditorWrapper = styled.div<{ AIEnabled?: boolean; mode: string; maxHeight?: string | number; + showFocusVisible?: boolean; }>` // Bottom border was getting clipped .CodeMirror.cm-s-duotone-light.CodeMirror-wrap { @@ -83,6 +84,17 @@ export const EditorWrapper = styled.div<{ text-transform: none; && { + ${(props) => + props.showFocusVisible && + ` + .CodeMirror-focused { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + z-index: 1 !important; + } + `} + .CodeMirror-cursor { border-right: none; border-left-width: 2px; @@ -390,12 +402,11 @@ export const EditorWrapper = styled.div<{ } } - &:focus { + &:focus-visible { .CodeMirror.cm-s-duotone-light { - border-color: ${(props) => - props.borderLess - ? "none" - : "var(--ads-v2-color-border-emphasis-plus)"}; + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); } } diff --git a/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx b/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx index f275b74469fe..c80ad0ee8ad6 100644 --- a/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx +++ b/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx @@ -95,14 +95,13 @@ export const StyledInputGroup = styled(InputGroup)<{ props.theme.colors.propertyPane.multiDropdownBoxHoverBg}; color: ${(props) => props.theme.colors.propertyPane.label}; - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); outline-offset: var(--ads-v2-offset-outline); } - &:hover, - &:focus { + &:hover { border-color: ${({ $isValid }) => $isValid ? "var(--ads-v2-color-border-emphasis)" diff --git a/app/client/src/components/propertyControls/IconSelectControl.tsx b/app/client/src/components/propertyControls/IconSelectControl.tsx index d968d0dc61d8..e4d8379ddba5 100644 --- a/app/client/src/components/propertyControls/IconSelectControl.tsx +++ b/app/client/src/components/propertyControls/IconSelectControl.tsx @@ -52,10 +52,10 @@ const StyledButton = styled(Button)` border: 1px solid var(--ads-v2-color-border-emphasis); } - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - border: 1px solid var(--ads-v2-color-border-emphasis); + outline-offset: var(--ads-v2-offset-outline); } `; diff --git a/app/client/src/components/propertyControls/IconSelectControlV2.tsx b/app/client/src/components/propertyControls/IconSelectControlV2.tsx index bdcdcc2e0b10..4d51f1de7203 100644 --- a/app/client/src/components/propertyControls/IconSelectControlV2.tsx +++ b/app/client/src/components/propertyControls/IconSelectControlV2.tsx @@ -53,10 +53,10 @@ const StyledButton = styled(Button)` border: 1px solid var(--ads-v2-color-border-emphasis); } - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - border: 1px solid var(--ads-v2-color-border-emphasis); + outline-offset: var(--ads-v2-offset-outline); } > span.bp3-button-text { diff --git a/app/client/src/index.css b/app/client/src/index.css index 9758abf54e07..871aa36fb5bc 100755 --- a/app/client/src/index.css +++ b/app/client/src/index.css @@ -22,23 +22,6 @@ body.dragging * { cursor: grabbing !important; } -/** - Disable outline completely from all components -*/ -:focus, -:focus-visible { - outline: none !important; - outline-offset: 0 !important; -} - -/** - Disable outline for adsv2 select component -*/ -.ads-v2-select.rc-select-focused { - outline: none !important; - outline-offset: 0 !important; -} - #root.overlay { opacity: 0; pointer-events: none; From 97ebfaa857662045bb7e75ead113483dc0793908 Mon Sep 17 00:00:00 2001 From: Sagar Khalasi Date: Mon, 13 Jan 2025 15:30:53 +0530 Subject: [PATCH 02/19] chore: Updated the mockdb code (#38603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description We have identified that the mock database is accessible to multiple stakeholders, increasing the risk of data corruption. To address this, we have commented out unnecessary and potentially flaky test code to ensure stability and reliability. Fixes # https://app.zenhub.com/workspaces/qa-63316faf86bb2e170ed2e46b/issues/gh/appsmithorg/appsmith/38602 ## Automation /ok-to-test tags="@tag.Datasource" ### :mag: Cypress test results > [!TIP] > 🟒 🟒 🟒 All cypress tests have passed! πŸŽ‰ πŸŽ‰ πŸŽ‰ > Workflow run: > Commit: f74f769b8a48b284380a296687c346ba904b595e > Cypress dashboard. > Tags: `@tag.Datasource` > Spec: >
Mon, 13 Jan 2025 09:51:58 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No ## Summary by CodeRabbit - **Tests** - Modified Cypress test for Mock Databases by removing specific query count and response verification assertions. --- .../e2e/Sanity/Datasources/MockDBs_Spec.ts | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts index 11df7b8477e8..d933bd60e216 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts @@ -61,17 +61,17 @@ describe( expect(interception.request.body.source).to.equal("SELF"); }); - dataSources.runQueryAndVerifyResponseViews({ - count: 1, - operator: "gte", - }); //minimum 1 rows are expected + // dataSources.runQueryAndVerifyResponseViews({ + // count: 1, + // operator: "gte", + // }); //minimum 1 rows are expected - AppSidebar.navigate(AppSidebarButton.Data); - dataSources - .getDatasourceListItemDescription(mockDBName) - .then(($queryCount) => - expect($queryCount).to.eq("2 queries in this app"), - ); + // AppSidebar.navigate(AppSidebarButton.Data); + // dataSources + // .getDatasourceListItemDescription(mockDBName) + // .then(($queryCount) => + // expect($queryCount).to.eq("2 queries in this app"), + // ); }); }); @@ -90,11 +90,11 @@ describe( assertHelper.AssertNetworkStatus("@trigger"); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); - dataSources.runQueryAndVerifyResponseViews({ - count: 1, - operator: "gte", - responseTypes: ["JSON", "RAW"], - }); + // dataSources.runQueryAndVerifyResponseViews({ + // count: 1, + // operator: "gte", + // responseTypes: ["JSON", "RAW"], + // }); }); }); }, From bfd66e50d6b39146345f0fea1f791561ff516b12 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Mon, 13 Jan 2025 15:49:09 +0530 Subject: [PATCH 03/19] chore: [ADS] Entity Tree Hover interactions (#38615) --- .../ads/src/List/List.stories.tsx | 1 + .../ads/src/List/List.styles.tsx | 9 ------ .../EntityItem/EntityItem.styles.ts | 8 +++++ .../EntityExplorer/EntityItem/EntityItem.tsx | 7 ---- .../EntityListTree/EntityListTree.styles.ts | 32 ++++++++++++------- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/app/client/packages/design-system/ads/src/List/List.stories.tsx b/app/client/packages/design-system/ads/src/List/List.stories.tsx index fbeb7039c06c..b706996413ea 100644 --- a/app/client/packages/design-system/ads/src/List/List.stories.tsx +++ b/app/client/packages/design-system/ads/src/List/List.stories.tsx @@ -38,6 +38,7 @@ const items = [ { startIcon: , title: "Action item 3", + isSelected: true, }, { startIcon: , diff --git a/app/client/packages/design-system/ads/src/List/List.styles.tsx b/app/client/packages/design-system/ads/src/List/List.styles.tsx index 15efd1bf333a..f27e179b4c12 100644 --- a/app/client/packages/design-system/ads/src/List/List.styles.tsx +++ b/app/client/packages/design-system/ads/src/List/List.styles.tsx @@ -93,7 +93,6 @@ export const StyledListItem = styled.div<{ flex-direction: column; ${({ size }) => Sizes[size]} - &[data-rightcontrolvisibility="hover"] { ${RightControlWrapper} { display: none; @@ -124,14 +123,6 @@ export const StyledListItem = styled.div<{ background-color: var(--ads-v2-colors-content-surface-active-bg); } - /* Focus styles */ - - &:focus-visible { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } - & .${ListItemTextOverflowClassName} { overflow: hidden; white-space: nowrap; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.styles.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.styles.ts index 5a1eafaa1dea..05cf52ead59e 100644 --- a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.styles.ts +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.styles.ts @@ -13,4 +13,12 @@ export const EntityEditableName = styled(Text)` min-width: 3ch; text-overflow: unset; } + + & input { + background-color: var(--ads-v2-color-bg); + padding-top: 0; + padding-bottom: 0; + height: 32px; + top: 0; + } `; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.tsx index def9e57dcbbd..cf5191006712 100644 --- a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.tsx +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityItem/EntityItem.tsx @@ -47,13 +47,6 @@ export const EntityItem = (props: EntityItemProps) => { () => ({ onChange: handleTitleChange, onKeyUp: handleKeyUp, - style: { - backgroundColor: "var(--ads-v2-color-bg)", - paddingTop: 0, - paddingBottom: 0, - height: "32px", - top: 0, - }, }), [handleKeyUp, handleTitleChange], ); diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityListTree/EntityListTree.styles.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityListTree/EntityListTree.styles.ts index cbb1cc9d03c5..f3c450400f91 100644 --- a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityListTree/EntityListTree.styles.ts +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EntityListTree/EntityListTree.styles.ts @@ -1,5 +1,6 @@ import styled from "styled-components"; import { Flex } from "../../../Flex"; +import { StyledListItem } from "../../../List/List.styles"; /** * This is used to add a spacing when collapse icon is not present @@ -12,9 +13,9 @@ export const PaddingOverrider = styled.div` width: 100%; & > div { - /* Override the padding of the entity item since collapsible icon can be on the left - * By default the padding on the left is 8px, so we need to reduce it to 4px - **/ + // Override the padding of the entity item since collapsible icon can be on the left + // By default the padding on the left is 8px, so we need to reduce it to 4px + padding-left: 4px; } `; @@ -33,16 +34,27 @@ export const CollapseWrapper = styled.div` export const EntityItemWrapper = styled(Flex)<{ "data-depth": number }>` border-radius: var(--ads-v2-border-radius); cursor: pointer; + user-select: none; padding-left: ${(props) => { return 4 + props["data-depth"] * 8; }}px; + /* selected style */ + // Set the selected style for wrapper and remove from list item + &[data-selected="true"] { background-color: var(--ads-v2-colors-content-surface-active-bg); } + ${StyledListItem} { + &[data-selected="true"] { + background-color: unset; + } + } + /* disabled style */ + // Set the disabled style for wrapper and remove from list item &[data-disabled="true"] { cursor: not-allowed; @@ -50,6 +62,12 @@ export const EntityItemWrapper = styled(Flex)<{ "data-depth": number }>` background-color: var(--ads-v2-colors-content-surface-default-bg); } + ${StyledListItem} { + &[data-disabled="true"] { + background-color: unset; + } + } + &:hover { background-color: var(--ads-v2-colors-content-surface-hover-bg); } @@ -57,12 +75,4 @@ export const EntityItemWrapper = styled(Flex)<{ "data-depth": number }>` &:active { background-color: var(--ads-v2-colors-content-surface-active-bg); } - - /* Focus styles */ - - &:focus-visible { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } `; From a7f7d3f237318800a069dc64651b8a6a3e6d178a Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Mon, 13 Jan 2025 18:01:04 +0530 Subject: [PATCH 04/19] fix: Issue with Api Body content type selection (#38597) --- app/client/cypress/support/Pages/ApiPage.ts | 4 +- .../components/ApiEditor/PostBodyData.tsx | 49 ++++---- .../store/pluginActionEditorActions.ts | 14 --- .../store/pluginActionEditorSelectors.ts | 23 ---- .../store/pluginEditorReducer.ts | 17 --- .../src/ce/constants/ReduxActionConstants.tsx | 2 - .../src/ce/navigation/FocusElements/AppIDE.ts | 17 +-- .../form/fields/DropdownFieldWrapper.tsx | 2 +- .../form/fields/DropdownWrapper.tsx | 6 +- .../form/fields/SelectField.tsx | 2 + app/client/src/navigation/FocusElements.ts | 1 - app/client/src/sagas/ApiPaneSagas.ts | 118 +++--------------- 12 files changed, 51 insertions(+), 204 deletions(-) diff --git a/app/client/cypress/support/Pages/ApiPage.ts b/app/client/cypress/support/Pages/ApiPage.ts index 398cb70cbcd1..a29e45df1359 100644 --- a/app/client/cypress/support/Pages/ApiPage.ts +++ b/app/client/cypress/support/Pages/ApiPage.ts @@ -67,9 +67,7 @@ export class ApiPage { "')]"; private _bodyTypeSelect = `//div[@data-testid="t--api-body-tab-switch"]`; private _bodyTypeToSelect = (subTab: string) => - "//div[contains(@class, 'rc-select-item-option')]//div[contains(text(),'" + - subTab + - "')]"; + ".rc-select-item-option:contains(" + subTab + ")"; private _rightPaneTab = (tab: string) => "//span[contains(text(), '" + tab + "')]/parent::button"; _visibleTextSpan = (spanText: string) => "//span[text()='" + spanText + "']"; diff --git a/app/client/src/PluginActionEditor/components/PluginActionForm/components/ApiEditor/PostBodyData.tsx b/app/client/src/PluginActionEditor/components/PluginActionForm/components/ApiEditor/PostBodyData.tsx index cee26fa60750..51b3e02d3ad4 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionForm/components/ApiEditor/PostBodyData.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionForm/components/ApiEditor/PostBodyData.tsx @@ -1,5 +1,5 @@ -import React, { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import React from "react"; +import { useSelector } from "react-redux"; import styled from "styled-components"; import { POST_BODY_FORMAT_OPTIONS, @@ -16,14 +16,14 @@ import { TabBehaviour, } from "components/editorComponents/CodeEditor/EditorConfig"; import { Classes } from "@appsmith/ads-old"; -import { - getPostBodyFormat, - updatePostBodyContentType, -} from "../../../../store"; import type { CodeEditorExpected } from "components/editorComponents/CodeEditor"; import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; import { createMessage, API_PANE_NO_BODY } from "ee/constants/messages"; -import { Select, Option } from "@appsmith/ads"; +import SelectField from "components/editorComponents/form/fields/SelectField"; +import { getFormValues } from "redux-form"; +import { API_EDITOR_FORM_NAME } from "ee/constants/forms"; +import type { Action } from "entities/Action"; +import { get } from "lodash"; const PostBodyContainer = styled.div` display: flex; @@ -31,6 +31,7 @@ const PostBodyContainer = styled.div` background-color: var(--ads-v2-color-bg); height: 100%; gap: var(--ads-v2-spaces-4); + .ads-v2-select { max-width: 250px; width: 100%; @@ -40,6 +41,7 @@ const PostBodyContainer = styled.div` const JSONEditorFieldWrapper = styled.div` /* margin: 0 30px; width: 65%; */ + .CodeMirror { height: auto; min-height: 250px; @@ -70,12 +72,12 @@ const expectedPostBody: CodeEditorExpected = { }; function PostBodyData(props: Props) { - const postBodyFormat = useSelector(getPostBodyFormat); - const dispatch = useDispatch(); - - const updateBodyContentType = useCallback((tab: string) => { - dispatch(updatePostBodyContentType(tab)); - }, []); + const formValues = useSelector(getFormValues(API_EDITOR_FORM_NAME)) as Action; + const postBodyFormat = get( + formValues, + "actionConfiguration.formData.apiContentType", + POST_BODY_FORMAT_OPTIONS.NONE, + ); const { dataTreePath, theme } = props; @@ -171,19 +173,14 @@ function PostBodyData(props: Props) { return ( - - {tabComponentsMap(postBodyFormat.value)} + + {tabComponentsMap(postBodyFormat)} ); } diff --git a/app/client/src/PluginActionEditor/store/pluginActionEditorActions.ts b/app/client/src/PluginActionEditor/store/pluginActionEditorActions.ts index 96cd57870a0f..2f57b3822f09 100644 --- a/app/client/src/PluginActionEditor/store/pluginActionEditorActions.ts +++ b/app/client/src/PluginActionEditor/store/pluginActionEditorActions.ts @@ -24,20 +24,6 @@ export const openPluginActionSettings = (payload: boolean) => ({ }, }); -export const updatePostBodyContentType = ( - title: string, -): ReduxAction<{ title: string }> => ({ - type: ReduxActionTypes.UPDATE_API_ACTION_BODY_CONTENT_TYPE, - payload: { title }, -}); - -export const setExtraFormData = ( - values: Record, -) => ({ - type: ReduxActionTypes.SET_EXTRA_FORMDATA, - payload: { values }, -}); - export const changeApi = ( id: string, isSaas: boolean, diff --git a/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts b/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts index b38e4bd1cc2f..d931e8210639 100644 --- a/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts +++ b/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts @@ -1,9 +1,6 @@ import type { AppState } from "ee/reducers"; import { createSelector } from "reselect"; -import { POST_BODY_FORM_DATA_KEY } from "./constants"; -import { POST_BODY_FORMAT_OPTIONS } from "../constants/CommonApiConstants"; - export const getActionEditorSavingMap = (state: AppState) => state.ui.pluginActionEditor.isSaving; @@ -38,26 +35,6 @@ export const isActionDeleting = (id: string) => (deletingMap) => id in deletingMap && deletingMap[id], ); -export const getFormData = (state: AppState) => - state.ui.pluginActionEditor.formData; - -type GetFormPostBodyFormat = (state: AppState) => { - label: string; - value: string; -}; - -export const getPostBodyFormat: GetFormPostBodyFormat = (state) => { - const formData = getFormData(state); - - if (POST_BODY_FORM_DATA_KEY in formData) { - return formData[POST_BODY_FORM_DATA_KEY]; - } - - return { - label: POST_BODY_FORMAT_OPTIONS.NONE, - value: POST_BODY_FORMAT_OPTIONS.NONE, - }; -}; export const getPluginActionConfigSelectedTab = (state: AppState) => state.ui.pluginActionEditor.selectedConfigTab; diff --git a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts index 3541e38fa1ac..a698845448d6 100644 --- a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts +++ b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts @@ -26,7 +26,6 @@ export interface PluginActionEditorState { isDirty: Record; runErrorMessage: Record; selectedConfigTab?: string; - formData: Record; debugger: PluginEditorDebuggerState; settingsOpen?: boolean; } @@ -38,7 +37,6 @@ const initialState: PluginActionEditorState = { isDeleting: {}, isDirty: {}, runErrorMessage: {}, - formData: {}, debugger: { open: false, responseTabHeight: ActionExecutionResizerHeight, @@ -136,21 +134,6 @@ export const handlers = { set(state, ["isRunning", id], false); set(state, ["runErrorMessage", id], error.message); }, - /** - * This redux action sets the extra form data field for an action. This is used to select the - * appropriate body type tab selection in the Rest API plugin based on the content-type. - * This redux action can be extended to other functionalities as well in the future. - */ - [ReduxActionTypes.SET_EXTRA_FORMDATA]: ( - state: PluginActionEditorState, - action: ReduxAction<{ - values: Record; - }>, - ) => { - const { values } = action.payload; - - set(state, ["formData"], values); - }, [ReduxActionTypes.SET_PLUGIN_ACTION_EDITOR_FORM_SELECTED_TAB]: ( state: PluginActionEditorState, action: ReduxAction<{ selectedTab: string }>, diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 0a3d912b1692..1c34ede4b084 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -769,7 +769,6 @@ const ActionActionTypes = { UPDATE_ACTION_SUCCESS: "UPDATE_ACTION_SUCCESS", DELETE_ACTION_INIT: "DELETE_ACTION_INIT", DELETE_ACTION_SUCCESS: "DELETE_ACTION_SUCCESS", - SET_EXTRA_FORMDATA: "SET_EXTRA_FORMDATA", MOVE_ACTION_INIT: "MOVE_ACTION_INIT", MOVE_ACTION_SUCCESS: "MOVE_ACTION_SUCCESS", COPY_ACTION_INIT: "COPY_ACTION_INIT", @@ -787,7 +786,6 @@ const ActionActionTypes = { TOGGLE_ACTION_EXECUTE_ON_LOAD_SUCCESS: "TOGGLE_ACTION_EXECUTE_ON_LOAD_SUCCESS", TOGGLE_ACTION_EXECUTE_ON_LOAD_INIT: "TOGGLE_ACTION_EXECUTE_ON_LOAD_INIT", - UPDATE_API_ACTION_BODY_CONTENT_TYPE: "UPDATE_API_ACTION_BODY_CONTENT_TYPE", }; const ActionActionErrorTypes = { diff --git a/app/client/src/ce/navigation/FocusElements/AppIDE.ts b/app/client/src/ce/navigation/FocusElements/AppIDE.ts index 336ddaeeee1a..d36bc7d2cc66 100644 --- a/app/client/src/ce/navigation/FocusElements/AppIDE.ts +++ b/app/client/src/ce/navigation/FocusElements/AppIDE.ts @@ -77,16 +77,11 @@ import { ActionExecutionResizerHeight } from "PluginActionEditor/components/Plug import { getPluginActionConfigSelectedTab, getPluginActionDebuggerState, - getFormData, - setExtraFormData, setPluginActionEditorDebuggerState, setPluginActionEditorSelectedTab, } from "PluginActionEditor/store"; import { EDITOR_TABS } from "constants/QueryEditorConstants"; -import { - API_EDITOR_TABS, - POST_BODY_FORMAT_OPTIONS, -} from "PluginActionEditor/constants/CommonApiConstants"; +import { API_EDITOR_TABS } from "PluginActionEditor/constants/CommonApiConstants"; export const AppIDEFocusElements: FocusElementsConfigList = { [FocusEntity.DATASOURCE_LIST]: [ @@ -155,16 +150,6 @@ export const AppIDEFocusElements: FocusElementsConfigList = { }, }, }, - { - type: FocusElementConfigType.Redux, - name: FocusElement.PluginActionFormData, - selector: getFormData, - setter: setExtraFormData, - defaultValue: { - label: POST_BODY_FORMAT_OPTIONS.NONE, - value: POST_BODY_FORMAT_OPTIONS.NONE, - }, - }, { type: FocusElementConfigType.Redux, name: FocusElement.PluginActionDebugger, diff --git a/app/client/src/components/editorComponents/form/fields/DropdownFieldWrapper.tsx b/app/client/src/components/editorComponents/form/fields/DropdownFieldWrapper.tsx index 7dc1ea75e4a0..4bab6e5d980f 100644 --- a/app/client/src/components/editorComponents/form/fields/DropdownFieldWrapper.tsx +++ b/app/client/src/components/editorComponents/form/fields/DropdownFieldWrapper.tsx @@ -40,7 +40,7 @@ function DropdownFieldWrapper(props: DropdownFieldWrapperProps) { > {props.options.map((option: SelectOptionProps) => { return ( - ); diff --git a/app/client/src/components/editorComponents/form/fields/DropdownWrapper.tsx b/app/client/src/components/editorComponents/form/fields/DropdownWrapper.tsx index 6c23cca3a500..b728ad86e495 100644 --- a/app/client/src/components/editorComponents/form/fields/DropdownWrapper.tsx +++ b/app/client/src/components/editorComponents/form/fields/DropdownWrapper.tsx @@ -24,6 +24,7 @@ interface DropdownWrapperProps { disabled?: boolean; dropdownMaxHeight?: string; enableSearch?: boolean; + testId?: string; } function DropdownWrapper(props: DropdownWrapperProps) { @@ -79,6 +80,7 @@ function DropdownWrapper(props: DropdownWrapperProps) { return (