Fix for slash commands blocker issues
(cherry picked from commit 6c0da9a380)
This commit is contained in:
parent
ccf017be12
commit
c2ecfa94b3
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="9" height="12" viewBox="0 0 9 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.79102 11.1094H4.11328V10.2832H3.87891C3.05273 10.2832 2.71875 9.90234 2.71875 8.96484V7.07812C2.71875 6.23438 2.29688 5.79492 1.43555 5.70703V5.56641C2.29688 5.47852 2.71875 5.03906 2.71875 4.19531V2.32031C2.71875 1.38281 3.05273 1.00195 3.87891 1.00195H4.11328V0.175781H3.79102C2.4082 0.175781 1.75781 0.826172 1.75781 2.19141V3.83203C1.75781 4.76953 1.43555 5.08008 0.46875 5.08008V6.19336C1.43555 6.19336 1.75781 6.50391 1.75781 7.44141V9.09375C1.75781 10.459 2.4082 11.1094 3.79102 11.1094Z" fill="#4B4848"/>
|
||||
<path d="M8.13305 11.1094H8.45531V10.2832H8.22094C7.39477 10.2832 7.06078 9.90234 7.06078 8.96484V7.07812C7.06078 6.23438 6.63891 5.79492 5.77758 5.70703V5.56641C6.63891 5.47852 7.06078 5.03906 7.06078 4.19531V2.32031C7.06078 1.38281 7.39477 1.00195 8.22094 1.00195H8.45531V0.175781H8.13305C6.75023 0.175781 6.09984 0.826172 6.09984 2.19141V3.83203C6.09984 4.76953 5.77758 5.08008 4.81078 5.08008V6.19336C5.77758 6.19336 6.09984 6.50391 6.09984 7.44141V9.09375C6.09984 10.459 6.75023 11.1094 8.13305 11.1094Z" fill="#4B4848"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="13" height="12" viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.38281 11.8271C6.71777 11.8271 6.99805 11.5605 6.99805 11.2324V6.68652H11.4141C11.7422 6.68652 12.0225 6.40625 12.0225 6.07129C12.0225 5.73633 11.7422 5.46289 11.4141 5.46289H6.99805V0.910156C6.99805 0.582031 6.71777 0.31543 6.38281 0.31543C6.04785 0.31543 5.77441 0.582031 5.77441 0.910156V5.46289H1.35156C1.02344 5.46289 0.743164 5.73633 0.743164 6.07129C0.743164 6.40625 1.02344 6.68652 1.35156 6.68652H5.77441V11.2324C5.77441 11.5605 6.04785 11.8271 6.38281 11.8271Z" fill="#4B4848"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 603 B |
|
|
@ -6,6 +6,7 @@ import { generateQuickCommands } from "./generateQuickCommands";
|
|||
import { Datasource } from "entities/Datasource";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import log from "loglevel";
|
||||
import { ENTITY_TYPE } from "entities/AppsmithConsole";
|
||||
|
||||
export const commandsHelper: HintHelper = (editor, data: any) => {
|
||||
let entitiesForSuggestions = Object.values(data).filter(
|
||||
|
|
@ -19,21 +20,15 @@ export const commandsHelper: HintHelper = (editor, data: any) => {
|
|||
{
|
||||
datasources,
|
||||
executeCommand,
|
||||
mutedHinting,
|
||||
pluginIdToImageLocation,
|
||||
recentEntities,
|
||||
updatePropertyValue,
|
||||
update,
|
||||
}: {
|
||||
mutedHinting?: boolean;
|
||||
datasources: Datasource[];
|
||||
executeCommand: (payload: { actionType: string; args?: any }) => void;
|
||||
pluginIdToImageLocation: Record<string, string>;
|
||||
recentEntities: string[];
|
||||
updatePropertyValue: (
|
||||
value: string,
|
||||
cursor?: number,
|
||||
preventAutoComplete?: boolean,
|
||||
) => void;
|
||||
update: (value: string) => void;
|
||||
},
|
||||
): boolean => {
|
||||
const currentEntityType = data[entityName]?.ENTITY_TYPE || "ACTION";
|
||||
|
|
@ -45,7 +40,8 @@ export const commandsHelper: HintHelper = (editor, data: any) => {
|
|||
const cursorBetweenBinding = checkIfCursorInsideBinding(editor);
|
||||
const value = editor.getValue();
|
||||
const slashIndex = value.lastIndexOf("/");
|
||||
const shouldShowBinding = (!value && !mutedHinting) || slashIndex > -1;
|
||||
const shouldShowBinding =
|
||||
slashIndex > -1 || (!value && currentEntityType === ENTITY_TYPE.WIDGET);
|
||||
if (!cursorBetweenBinding && shouldShowBinding) {
|
||||
const searchText = value.substring(slashIndex + 1);
|
||||
const list = generateQuickCommands(
|
||||
|
|
@ -81,16 +77,19 @@ export const commandsHelper: HintHelper = (editor, data: any) => {
|
|||
selectedHint: 1,
|
||||
};
|
||||
CodeMirror.on(hints, "pick", (selected: CommandsCompletion) => {
|
||||
const updatedValue = value.slice(
|
||||
0,
|
||||
value.length - searchText.length - 1,
|
||||
);
|
||||
if (selected.action && typeof selected.action === "function") {
|
||||
updatePropertyValue(updatedValue, updatedValue.length, true);
|
||||
selected.action();
|
||||
} else {
|
||||
updatePropertyValue(updatedValue + selected.text);
|
||||
}
|
||||
update(value.slice(0, slashIndex) + selected.text);
|
||||
setTimeout(() => {
|
||||
editor.focus();
|
||||
editor.setCursor({
|
||||
line: editor.lineCount() - 1,
|
||||
ch: editor.getLine(editor.lineCount() - 1).length - 2,
|
||||
});
|
||||
if (selected.action && typeof selected.action === "function") {
|
||||
selected.action();
|
||||
} else {
|
||||
CodeMirror.signal(editor, "postPick");
|
||||
}
|
||||
});
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { data, render, ...rest } = selected;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,13 @@ import sortBy from "lodash/sortBy";
|
|||
import { PluginType } from "entities/Action";
|
||||
import { ReactComponent as ApisIcon } from "assets/icons/menu/api-colored.svg";
|
||||
import { ReactComponent as DataSourcesColoredIcon } from "assets/icons/menu/datasource-colored.svg";
|
||||
import { ReactComponent as NewPlus } from "assets/icons/menu/new-plus.svg";
|
||||
import { ReactComponent as Binding } from "assets/icons/menu/binding.svg";
|
||||
|
||||
enum Shortcuts {
|
||||
PLUS = "PLUS",
|
||||
BINDING = "BINDING",
|
||||
}
|
||||
export const generateQuickCommands = (
|
||||
entitiesForSuggestions: any[],
|
||||
currentEntityType: string,
|
||||
|
|
@ -25,19 +31,20 @@ export const generateQuickCommands = (
|
|||
) => {
|
||||
const suggestionsHeader: CommandsCompletion = commandsHeader("Bind Data");
|
||||
const createNewHeader: CommandsCompletion = commandsHeader("Create New");
|
||||
recentEntities.reverse();
|
||||
const newBinding: CommandsCompletion = generateCreateNewCommand({
|
||||
text: "{{}}",
|
||||
displayText: "New Binding",
|
||||
shortcut: "{{}}",
|
||||
shortcut: Shortcuts.BINDING,
|
||||
});
|
||||
const newDatasource: CommandsCompletion = generateCreateNewCommand({
|
||||
const newIntegration: CommandsCompletion = generateCreateNewCommand({
|
||||
text: "",
|
||||
displayText: "New Datasource",
|
||||
action: () =>
|
||||
executeCommand({
|
||||
actionType: "NEW_DATASOURCE",
|
||||
actionType: "NEW_INTEGRATION",
|
||||
}),
|
||||
shortcut: "datasource.new",
|
||||
shortcut: Shortcuts.PLUS,
|
||||
});
|
||||
const suggestions = entitiesForSuggestions.map((suggestion: any) => {
|
||||
const name = suggestion.name || suggestion.widgetName;
|
||||
|
|
@ -45,7 +52,6 @@ export const generateQuickCommands = (
|
|||
text: currentEntityType === "WIDGET" ? `{{${name}.data}}` : `{{${name}}}`,
|
||||
displayText: `${name}`,
|
||||
className: "CodeMirror-commands",
|
||||
shortcut: "{{}}",
|
||||
data: suggestion,
|
||||
render: (element: HTMLElement, self: any, data: any) => {
|
||||
const pluginType = data.data.pluginType as PluginType;
|
||||
|
|
@ -65,7 +71,6 @@ export const generateQuickCommands = (
|
|||
text: "",
|
||||
displayText: `${action.name}`,
|
||||
className: "CodeMirror-commands",
|
||||
shortcut: `${action.name}.new`,
|
||||
data: action,
|
||||
action: () =>
|
||||
executeCommand({
|
||||
|
|
@ -88,7 +93,7 @@ export const generateQuickCommands = (
|
|||
suggestions,
|
||||
searchText,
|
||||
recentEntities,
|
||||
currentEntityType === "WIDGET" ? 2 : 3,
|
||||
5,
|
||||
);
|
||||
suggestionsMatchingSearchText.push(
|
||||
...matchingCommands([newBinding], searchText, []),
|
||||
|
|
@ -105,7 +110,7 @@ export const generateQuickCommands = (
|
|||
);
|
||||
if (currentEntityType === "WIDGET") {
|
||||
createNewCommandsMatchingSearchText.push(
|
||||
...matchingCommands([newDatasource], searchText, []),
|
||||
...matchingCommands([newIntegration], searchText, []),
|
||||
);
|
||||
}
|
||||
let list: CommandsCompletion[] = [];
|
||||
|
|
@ -123,13 +128,12 @@ const matchingCommands = (
|
|||
list: any,
|
||||
searchText: string,
|
||||
recentEntities: string[] = [],
|
||||
limit = 2,
|
||||
limit = 5,
|
||||
) => {
|
||||
list = list.filter((action: any) => {
|
||||
return (
|
||||
action.displayText.toLowerCase().startsWith(searchText.toLowerCase()) ||
|
||||
action.shortcut.toLowerCase().startsWith(searchText.toLowerCase())
|
||||
);
|
||||
return action.displayText
|
||||
.toLowerCase()
|
||||
.startsWith(searchText.toLowerCase());
|
||||
});
|
||||
list = sortBy(list, (a: any) => {
|
||||
return (
|
||||
|
|
@ -171,7 +175,11 @@ const generateCreateNewCommand = ({
|
|||
action: action,
|
||||
render: (element: HTMLElement, self: any, data: any) => {
|
||||
ReactDOM.render(
|
||||
<Command name={data.displayText} shortcut={data.shortcut} />,
|
||||
<Command
|
||||
customText={data.customText}
|
||||
name={data.displayText}
|
||||
shortcut={data.shortcut}
|
||||
/>,
|
||||
element,
|
||||
);
|
||||
},
|
||||
|
|
@ -181,7 +189,8 @@ function Command(props: {
|
|||
pluginType?: PluginType;
|
||||
imgSrc?: string;
|
||||
name: string;
|
||||
shortcut: string;
|
||||
shortcut: Shortcuts;
|
||||
customText?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="command-container">
|
||||
|
|
@ -193,9 +202,12 @@ function Command(props: {
|
|||
SAAS: <DataSourcesColoredIcon />,
|
||||
}[props.pluginType]}
|
||||
{props.imgSrc && <img src={props.imgSrc} />}
|
||||
{props.shortcut &&
|
||||
{ [Shortcuts.BINDING]: <Binding />, [Shortcuts.PLUS]: <NewPlus /> }[
|
||||
props.shortcut
|
||||
]}
|
||||
<span>{props.name}</span>
|
||||
</div>
|
||||
<span className="shortcut">{props.shortcut}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ export type EditorStyleProps = {
|
|||
disabled?: boolean;
|
||||
link?: string;
|
||||
showLightningMenu?: boolean;
|
||||
mutedHinting?: boolean;
|
||||
dataTreePath?: string;
|
||||
evaluatedValue?: any;
|
||||
expected?: string;
|
||||
|
|
@ -227,6 +226,7 @@ class CodeEditor extends Component<Props, State> {
|
|||
editor.on("cursorActivity", this.handleCursorMovement);
|
||||
editor.on("focus", this.onFocusTrigger);
|
||||
editor.on("blur", this.handleEditorBlur);
|
||||
editor.on("postPick", () => this.handleAutocompleteVisibility(editor));
|
||||
if (this.props.height) {
|
||||
editor.setSize("100%", this.props.height);
|
||||
} else {
|
||||
|
|
@ -290,11 +290,9 @@ class CodeEditor extends Component<Props, State> {
|
|||
showLightningMenu?: boolean,
|
||||
additionalDynamicData?: Record<string, Record<string, unknown>>,
|
||||
) {
|
||||
return (showLightningMenu !== false ? hinting : [bindingHint]).map(
|
||||
(helper) => {
|
||||
return helper(editor, dynamicData, additionalDynamicData);
|
||||
},
|
||||
);
|
||||
return hinting.map((helper) => {
|
||||
return helper(editor, dynamicData, additionalDynamicData);
|
||||
});
|
||||
}
|
||||
|
||||
onFocusTrigger = (cm: CodeMirror.Editor) => {
|
||||
|
|
@ -328,10 +326,12 @@ class CodeEditor extends Component<Props, State> {
|
|||
handleEditorFocus = () => {
|
||||
this.setState({ isFocused: true });
|
||||
if (this.props.size === EditorSize.COMPACT) {
|
||||
const inputValue = this.props.input.value;
|
||||
this.editor.setOption("lineWrapping", true);
|
||||
this.editor.setValue(inputValue);
|
||||
this.editor.setCursor(inputValue.length);
|
||||
this.editor.operation(() => {
|
||||
const inputValue = this.props.input.value;
|
||||
this.editor.setOption("lineWrapping", true);
|
||||
this.editor.setValue(inputValue);
|
||||
this.editor.setCursor(inputValue.length);
|
||||
});
|
||||
}
|
||||
if (this.editor.getValue().length === 0)
|
||||
this.handleAutocompleteVisibility(this.editor);
|
||||
|
|
@ -339,12 +339,10 @@ class CodeEditor extends Component<Props, State> {
|
|||
|
||||
handleEditorBlur = () => {
|
||||
this.handleChange();
|
||||
// on blur closing the binding prompt for an editor regardless.
|
||||
this.setState({ isFocused: false });
|
||||
if (this.props.size === EditorSize.COMPACT) {
|
||||
this.editor.setOption("lineWrapping", false);
|
||||
}
|
||||
|
||||
this.editor.setOption("matchBrackets", false);
|
||||
};
|
||||
|
||||
|
|
@ -375,7 +373,8 @@ class CodeEditor extends Component<Props, State> {
|
|||
const inputValue = this.props.input.value || "";
|
||||
if (
|
||||
this.props.input.onChange &&
|
||||
value !== inputValue &&
|
||||
(value !== inputValue ||
|
||||
_.get(this.editor, "state.completionActive.startLen") === 0) &&
|
||||
this.state.isFocused
|
||||
) {
|
||||
this.props.input.onChange(value);
|
||||
|
|
@ -383,7 +382,8 @@ class CodeEditor extends Component<Props, State> {
|
|||
CodeEditor.updateMarkings(this.editor, this.props.marking);
|
||||
};
|
||||
|
||||
handleAutocompleteVisibility = (cm: CodeMirror.Editor, force?: boolean) => {
|
||||
handleAutocompleteVisibility = (cm: CodeMirror.Editor) => {
|
||||
if (!this.state.isFocused) return;
|
||||
const expected = this.props.expected ? this.props.expected : "";
|
||||
const { entityName } = getEntityNameAndPropertyPath(
|
||||
this.props.dataTreePath || "",
|
||||
|
|
@ -391,17 +391,16 @@ class CodeEditor extends Component<Props, State> {
|
|||
let hinterOpen = false;
|
||||
for (let i = 0; i < this.hinters.length; i++) {
|
||||
hinterOpen = this.hinters[i].showHint(cm, expected, entityName, {
|
||||
mutedHinting: force ? !force : this.props.mutedHinting,
|
||||
datasources: this.props.datasources.list,
|
||||
pluginIdToImageLocation: this.props.pluginIdToImageLocation,
|
||||
updatePropertyValue: this.updatePropertyValue.bind(this),
|
||||
recentEntities: this.props.recentEntities,
|
||||
update: this.props.input.onChange?.bind(this),
|
||||
executeCommand: (payload: any) => {
|
||||
this.props.executeCommand({
|
||||
...payload,
|
||||
callback: (binding: string) => {
|
||||
const value = this.editor.getValue() + binding;
|
||||
this.updatePropertyValue(value);
|
||||
this.updatePropertyValue(value, value.length);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
@ -432,20 +431,13 @@ class CodeEditor extends Component<Props, State> {
|
|||
this.editor.setValue(value);
|
||||
}
|
||||
this.editor.focus();
|
||||
if (cursor === undefined) {
|
||||
if (value) {
|
||||
cursor = value.length - 2;
|
||||
} else {
|
||||
cursor = 1;
|
||||
}
|
||||
}
|
||||
this.editor.setCursor({
|
||||
line: 0,
|
||||
ch: cursor,
|
||||
line: cursor || this.editor.lineCount() - 1,
|
||||
ch: this.editor.getLine(this.editor.lineCount() - 1).length - 2,
|
||||
});
|
||||
this.setState({ isFocused: true }, () => {
|
||||
if (preventAutoComplete) return;
|
||||
this.handleAutocompleteVisibility(this.editor, true);
|
||||
this.handleAutocompleteVisibility(this.editor);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -598,7 +590,10 @@ class CodeEditor extends Component<Props, State> {
|
|||
)}
|
||||
<BindingPrompt
|
||||
editorTheme={this.props.theme}
|
||||
isOpen={showBindingPrompt(showEvaluatedValue, input.value)}
|
||||
isOpen={
|
||||
showBindingPrompt(showEvaluatedValue, input.value) &&
|
||||
!_.get(this.editor, "state.completionActive")
|
||||
}
|
||||
promptMessage={this.props.promptMessage}
|
||||
showLightningMenu={this.props.showLightningMenu}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
showLightningMenu={false}
|
||||
theme={props.theme}
|
||||
/>
|
||||
</Flex>
|
||||
|
|
@ -149,7 +148,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
dataTreePath={`${props.dataTreePath}[${index}].value`}
|
||||
expected={FIELD_VALUES.API_ACTION.params}
|
||||
hoverInteraction
|
||||
mutedHinting
|
||||
name={`${field}.value`}
|
||||
placeholder={`Value ${index + 1}`}
|
||||
theme={props.theme}
|
||||
|
|
@ -169,7 +167,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
)
|
||||
}
|
||||
expected={FIELD_VALUES.API_ACTION.params}
|
||||
mutedHinting
|
||||
name={`${field}.value`}
|
||||
placeholder={
|
||||
props.placeholder
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ class DynamicTextControl extends BaseControl<
|
|||
configProperty,
|
||||
evaluationSubstitutionType,
|
||||
label,
|
||||
mutedHinting,
|
||||
placeholderText,
|
||||
responseType,
|
||||
} = this.props;
|
||||
|
|
@ -105,7 +104,6 @@ class DynamicTextControl extends BaseControl<
|
|||
dataTreePath={dataTreePath}
|
||||
evaluationSubstitutionType={evaluationSubstitutionType}
|
||||
mode={mode}
|
||||
mutedHinting={mutedHinting}
|
||||
name={this.props.configProperty}
|
||||
placeholder={placeholderText}
|
||||
size={EditorSize.EXTENDED}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export const CodemirrorHintStyles = createGlobalStyle<{
|
|||
pointer-events: none !important;
|
||||
font-family: ${(props) => props.theme.fonts.text};
|
||||
${(props) => getTypographyByKey(props, "p3")}
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.CodeMirror-commands {
|
||||
|
|
@ -86,6 +87,8 @@ export const CodemirrorHintStyles = createGlobalStyle<{
|
|||
margin-right: 7px;
|
||||
}
|
||||
svg {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ function PostBodyData(props: Props) {
|
|||
dataTreePath={`${dataTreePath}.body`}
|
||||
expected={FIELD_VALUES.API_ACTION.body}
|
||||
mode={EditorModes.JSON_WITH_BINDING}
|
||||
mutedHinting
|
||||
name="actionConfiguration.body"
|
||||
placeholder={
|
||||
'{\n "name":"{{ inputName.property }}",\n "preference":"{{ dropdownName.property }}"\n}\n\n\\\\Take widget inputs using {{ }}'
|
||||
|
|
|
|||
|
|
@ -183,14 +183,12 @@ function RapidApiEditorForm(props: Props) {
|
|||
<DynamicTextField
|
||||
disabled
|
||||
leftImage={providerImage}
|
||||
mutedHinting
|
||||
name="provider.name"
|
||||
placeholder="Provider name"
|
||||
/>
|
||||
<DynamicTextField
|
||||
disabled
|
||||
leftIcon={FormIcons.SLASH_ICON}
|
||||
mutedHinting
|
||||
name="actionConfiguration.path"
|
||||
placeholder="v1/method"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -743,7 +743,7 @@ function* executeCommand(
|
|||
const pageId = yield select(getCurrentPageId);
|
||||
const applicationId = yield select(getCurrentApplicationId);
|
||||
switch (actionPayload.payload.actionType) {
|
||||
case "NEW_DATASOURCE":
|
||||
case "NEW_INTEGRATION":
|
||||
history.push(
|
||||
INTEGRATION_EDITOR_URL(applicationId, pageId, INTEGRATION_TABS.NEW),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class FormControlRegistry {
|
|||
});
|
||||
FormControlFactory.registerControlBuilder("QUERY_DYNAMIC_TEXT", {
|
||||
buildPropertyControl(controlProps: DynamicTextFieldProps): JSX.Element {
|
||||
return <DynamicTextControl {...controlProps} mutedHinting />;
|
||||
return <DynamicTextControl {...controlProps} />;
|
||||
},
|
||||
});
|
||||
FormControlFactory.registerControlBuilder("QUERY_DYNAMIC_INPUT_TEXT", {
|
||||
|
|
|
|||
Loading…
Reference in New Issue