diff --git a/.all-contributorsrc b/.all-contributorsrc index d614d3c8f0..cdcc6091b5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -205,7 +205,16 @@ "avatar_url": "https://avatars0.githubusercontent.com/u/25309929?v=4", "profile": "https://github.com/A-Scratchy", "contributions": [ - "code" + "code" + ] + }, + { + "login": "sumanthyedoti", + "name": "Sumanth Yedoti", + "avatar_url": "https://avatars3.githubusercontent.com/u/30371888?v=4", + "profile": "https://github.com/sumanthyedoti", + "contributions": [ + "code" ] } ], diff --git a/README.md b/README.md index 6c2da1c1d3..0370fb76c7 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,9 @@ The Appsmith platform is available under the [Apache License 2.0](https://www.ap
Prashant Chaubey

💻
Adam

💻 + +
Sumanth Yedoti

🔧 💻 + diff --git a/app/client/cypress/integration/Smoke_TestSuite/Binding/No_Binding_Prompt_spec.js b/app/client/cypress/integration/Smoke_TestSuite/Binding/No_Binding_Prompt_spec.js new file mode 100644 index 0000000000..b8317bb468 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/Binding/No_Binding_Prompt_spec.js @@ -0,0 +1,18 @@ +const dsl = require("../../../fixtures/inputdsl.json"); +const widgetsPage = require("../../../locators/Widgets.json"); +const dynamicInput = require("../../../locators/DynamicInput.json"); + +describe("Binding prompt", function() { + before(() => { + cy.addDsl(dsl); + }); + + it("Show binding prompt when there are no bindings in the editor", () => { + cy.openPropertyPane("inputwidget"); + cy.get(widgetsPage.defaultInput).type(" "); + cy.get(dynamicInput.bindingPrompt).should("be.visible"); + + cy.get(widgetsPage.defaultInput).type("{{"); + cy.get(dynamicInput.bindingPrompt).should("not.be.visible"); + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/DisplayWidgets/video_spec.js b/app/client/cypress/integration/Smoke_TestSuite/DisplayWidgets/video_spec.js index d447fcb5f6..243a441c3b 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/DisplayWidgets/video_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/DisplayWidgets/video_spec.js @@ -48,6 +48,9 @@ describe("Video Widget Functionality", function() { it("Update video url and check play and pause functionality validation", function() { cy.testCodeMirror(testdata.videoUrl); + cy.get(".CodeMirror textarea") + .first() + .blur(); cy.get(widgetsPage.autoPlay).click(); cy.wait("@updateLayout").should( "have.nested.property", diff --git a/app/client/cypress/locators/DynamicInput.json b/app/client/cypress/locators/DynamicInput.json index 5c3eb61356..8f34ce8219 100644 --- a/app/client/cypress/locators/DynamicInput.json +++ b/app/client/cypress/locators/DynamicInput.json @@ -1,5 +1,6 @@ { "input": ".CodeMirror textarea", "hints": "ul.CodeMirror-hints", - "evaluatedValue": ".t--CodeEditor-evaluatedValue" + "evaluatedValue": ".t--CodeEditor-evaluatedValue", + "bindingPrompt": ".t--no-binding-prompt" } diff --git a/app/client/src/components/editorComponents/CodeEditor/BindingPrompt.tsx b/app/client/src/components/editorComponents/CodeEditor/BindingPrompt.tsx new file mode 100644 index 0000000000..4efb6526f9 --- /dev/null +++ b/app/client/src/components/editorComponents/CodeEditor/BindingPrompt.tsx @@ -0,0 +1,48 @@ +import React, { useRef } from "react"; +import styled from "styled-components"; +import { Colors } from "constants/Colors"; + +const Wrapper = styled.span<{ visible: boolean; bottomOffset: number }>` + padding: 8px; + font-size: 12px; + color: ${Colors.GRAY_CHATEAU}; + border-radius: 2px; + background-color: ${Colors.BLUE_CHARCOAL}; + position: absolute; + bottom: ${props => -props.bottomOffset}px; + width: 100%; + line-height: 13px; + visibility: ${props => (props.visible ? "visible" : "hidden")}; + z-index: 1; +`; + +const CurlyBraces = styled.span` + color: white; + background-color: #f3672a; + border-radius: 2px; + padding: 2px; + margin: 0px 2px; +`; + +const BindingPrompt = (props: { isOpen: boolean }): JSX.Element => { + const promptRef = useRef(null); + let bottomOffset = 30; + + if (promptRef.current) { + const boundingRect = promptRef.current.getBoundingClientRect(); + bottomOffset = boundingRect.height; + } + + return ( + + Type {"{{"} to see a list of variables + + ); +}; + +export default BindingPrompt; diff --git a/app/client/src/components/editorComponents/CodeEditor/index.tsx b/app/client/src/components/editorComponents/CodeEditor/index.tsx index 7c64d1dfe4..c3fb0a30f2 100644 --- a/app/client/src/components/editorComponents/CodeEditor/index.tsx +++ b/app/client/src/components/editorComponents/CodeEditor/index.tsx @@ -36,6 +36,7 @@ import { import { bindingMarker } from "components/editorComponents/CodeEditor/markHelpers"; import { bindingHint } from "components/editorComponents/CodeEditor/hintHelpers"; import { retryPromise } from "utils/AppsmithUtils"; +import BindingPrompt from "./BindingPrompt"; const LightningMenu = lazy(() => retryPromise(() => import("components/editorComponents/LightningMenu")), @@ -91,9 +92,7 @@ class CodeEditor extends Component { }; textArea = React.createRef(); - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore - editor: CodeMirror.Editor; + editor!: CodeMirror.Editor; hinters: Hinter[] = []; constructor(props: Props) { @@ -272,6 +271,7 @@ class CodeEditor extends Component { theme, disabled, className, + placeholder, showLightningMenu, dataTreePath, dynamicData, @@ -291,6 +291,10 @@ class CodeEditor extends Component { ("evaluatedValue" in this.props || ("dataTreePath" in this.props && !!this.props.dataTreePath)); + const showBindingPrompt = + (!this.props.input.value?.includes("{{") || !this.props.input.value) && + showEvaluatedValue; + return ( { className="leftImageStyles" /> )} -