From 44e657fe120d92cf0367cae5f23d686fc3f360a5 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Wed, 3 Jun 2020 17:27:24 +0000 Subject: [PATCH] refactored function name reverted binding logic --- .../DynamicAutocompleteInput.tsx | 26 ++++++++---- app/client/src/utils/DynamicBindingUtils.ts | 42 ++++++++++--------- .../src/utils/autocomplete/TernServer.ts | 7 +++- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/app/client/src/components/editorComponents/DynamicAutocompleteInput.tsx b/app/client/src/components/editorComponents/DynamicAutocompleteInput.tsx index dfac98dcef..16c9efa601 100644 --- a/app/client/src/components/editorComponents/DynamicAutocompleteInput.tsx +++ b/app/client/src/components/editorComponents/DynamicAutocompleteInput.tsx @@ -17,7 +17,7 @@ import ErrorTooltip from "components/editorComponents/ErrorTooltip"; import HelperTooltip from "components/editorComponents/HelperTooltip"; import { WrappedFieldInputProps, WrappedFieldMetaProps } from "redux-form"; import _ from "lodash"; -import { parseDynamicString } from "utils/DynamicBindingUtils"; +import { getDynamicStringSegments } from "utils/DynamicBindingUtils"; import { DataTree } from "entities/DataTree/dataTreeFactory"; import { Theme } from "constants/DefaultTheme"; import AnalyticsUtil from "utils/AnalyticsUtil"; @@ -324,6 +324,7 @@ class DynamicAutocompleteInput extends Component { }); this.editor.on("change", _.debounce(this.handleChange, 300)); + this.editor.on("change", this.handleAutocompleteVisibility); this.editor.on("keyup", this.handleAutocompleteHide); this.editor.on("focus", this.handleEditorFocus); this.editor.on("blur", this.handleEditorBlur); @@ -409,7 +410,6 @@ class DynamicAutocompleteInput extends Component { globalScope: this.props.dynamicData, }); } - this.editor.on("cursorActivity", this.handleAutocompleteVisibility); } handleEditorFocus = () => { @@ -447,20 +447,30 @@ class DynamicAutocompleteInput extends Component { let cursorBetweenBinding = false; const cursor = this.editor.getCursor(); const value = this.editor.getValue(); + let cursorIndex = cursor.ch; + if (cursor.line > 0) { + for (let lineIndex = 0; lineIndex < cursor.line; lineIndex++) { + const line = this.editor.getLine(lineIndex); + // Add line length + 1 for new line character + cursorIndex = cursorIndex + line.length + 1; + } + } + const stringSegments = getDynamicStringSegments(value); + // count of chars processed let cumulativeCharCount = 0; - parseDynamicString(value).forEach(segment => { + stringSegments.forEach((segment: string) => { const start = cumulativeCharCount; const dynamicStart = segment.indexOf("{{"); const dynamicDoesStart = dynamicStart > -1; const dynamicEnd = segment.indexOf("}}"); const dynamicDoesEnd = dynamicEnd > -1; - const dynamicStartIndex = dynamicStart + start + 1; - const dynamicEndIndex = dynamicEnd + start + 1; + const dynamicStartIndex = dynamicStart + start + 2; + const dynamicEndIndex = dynamicEnd + start; if ( dynamicDoesStart && - cursor.ch > dynamicStartIndex && - ((dynamicDoesEnd && cursor.ch < dynamicEndIndex) || - (!dynamicDoesEnd && cursor.ch > dynamicStartIndex)) + cursorIndex >= dynamicStartIndex && + ((dynamicDoesEnd && cursorIndex <= dynamicEndIndex) || + (!dynamicDoesEnd && cursorIndex >= dynamicStartIndex)) ) { cursorBetweenBinding = true; } diff --git a/app/client/src/utils/DynamicBindingUtils.ts b/app/client/src/utils/DynamicBindingUtils.ts index 20b86e971a..0bffe96554 100644 --- a/app/client/src/utils/DynamicBindingUtils.ts +++ b/app/client/src/utils/DynamicBindingUtils.ts @@ -31,15 +31,15 @@ export const isDynamicValue = (value: string): boolean => DATA_BIND_REGEX.test(value); //{{}}{{}}} -export function parseDynamicString(dynamicString: string): string[] { - let parsedDynamicValues = []; +export function getDynamicStringSegments(dynamicString: string): string[] { + let stringSegments = []; const indexOfDoubleParanStart = dynamicString.indexOf("{{"); if (indexOfDoubleParanStart === -1) { return [dynamicString]; } //{{}}{{}}} const firstString = dynamicString.substring(0, indexOfDoubleParanStart); - firstString && parsedDynamicValues.push(firstString); + firstString && stringSegments.push(firstString); let rest = dynamicString.substring( indexOfDoubleParanStart, dynamicString.length, @@ -55,11 +55,11 @@ export function parseDynamicString(dynamicString: string): string[] { } else if (char === "}") { sum--; if (prevChar === "}" && sum === 0) { - parsedDynamicValues.push(rest.substring(0, i + 1)); + stringSegments.push(rest.substring(0, i + 1)); rest = rest.substring(i + 1, rest.length); if (rest) { - parsedDynamicValues = parsedDynamicValues.concat( - parseDynamicString(rest), + stringSegments = stringSegments.concat( + getDynamicStringSegments(rest), ); break; } @@ -69,7 +69,7 @@ export function parseDynamicString(dynamicString: string): string[] { if (sum !== 0 && dynamicString !== "") { return [dynamicString]; } - return parsedDynamicValues; + return stringSegments; } const getAllPaths = ( @@ -95,24 +95,24 @@ const getAllPaths = ( export const getDynamicBindings = ( dynamicString: string, -): { mustaches: string[]; jsSnippets: string[] } => { +): { stringSegments: string[]; jsSnippets: string[] } => { // Protect against bad string parse if (!dynamicString || !_.isString(dynamicString)) { - return { mustaches: [], jsSnippets: [] }; + return { stringSegments: [], jsSnippets: [] }; } const sanitisedString = dynamicString.trim(); // Get the {{binding}} bound values - const bindings = parseDynamicString(sanitisedString); + const stringSegments = getDynamicStringSegments(sanitisedString); // Get the "binding" path values - const paths = bindings.map(binding => { - const length = binding.length; - const matches = isDynamicValue(binding); + const paths = stringSegments.map(segment => { + const length = segment.length; + const matches = isDynamicValue(segment); if (matches) { - return binding.substring(2, length - 2); + return segment.substring(2, length - 2); } return ""; }); - return { mustaches: bindings, jsSnippets: paths }; + return { stringSegments: stringSegments, jsSnippets: paths }; }; // Paths are expected to have "{name}.{path}" signature @@ -162,8 +162,10 @@ export const getDynamicValue = ( includeTriggers = false, ): JSExecutorResult => { // Get the {{binding}} bound values - const { mustaches, jsSnippets } = getDynamicBindings(dynamicBinding); - if (mustaches.length) { + const { stringSegments: stringSegments, jsSnippets } = getDynamicBindings( + dynamicBinding, + ); + if (stringSegments.length) { // Get the Data Tree value of those "binding "paths const values = jsSnippets.map((jsSnippet, index) => { if (jsSnippet) { @@ -174,16 +176,16 @@ export const getDynamicValue = ( return { result: result.result }; } } else { - return { result: mustaches[index], triggers: [] }; + return { result: stringSegments[index], triggers: [] }; } }); // if it is just one binding, no need to create template string - if (mustaches.length === 1) return values[0]; + if (stringSegments.length === 1) return values[0]; // else return a string template with bindings const templateString = createDynamicValueString( dynamicBinding, - mustaches, + stringSegments, values.map(v => v.result), ); return { diff --git a/app/client/src/utils/autocomplete/TernServer.ts b/app/client/src/utils/autocomplete/TernServer.ts index efb3936264..129a3d6158 100644 --- a/app/client/src/utils/autocomplete/TernServer.ts +++ b/app/client/src/utils/autocomplete/TernServer.ts @@ -137,8 +137,11 @@ class TernServer { .sort((a, b) => { return a.text.toLowerCase().localeCompare(b.text.toLowerCase()); }); - const otherCompletions = completions.filter(c => c.origin !== "dataTree"); - return [...dataTreeCompletions, ...otherCompletions]; + const docCompletetions = completions.filter(c => c.origin === "[doc]"); + const otherCompletions = completions.filter( + c => c.origin !== "dataTree" && c.origin !== "[doc]", + ); + return [...docCompletetions, ...dataTreeCompletions, ...otherCompletions]; } typeToIcon(type: string) {