chore: Move constants, types and utils to their own files in Action Creator (#16947)
* Move constants and regex to their own files from index and fields file * Move types to to its own file * Move utils to its file * Add proper types for functions in fields file * Rename Switch -> Switchtype * Fix imports * Fix NAVIGATION_TARGET_FIELD_OPTIONS constant so that the build works * Jest tests to cover the utils * Add jest test cases * Update cases * Code review changes
This commit is contained in:
parent
a64f27ce27
commit
4e9068ddba
|
|
@ -7,7 +7,7 @@ export function createMessage(
|
|||
|
||||
/*
|
||||
For self hosted, it displays the string "Appsmith Community v1.10.0" or "Appsmith Business v1.10.0".
|
||||
For cloud hosting, it displays "Appsmith v1.10.0".
|
||||
For cloud hosting, it displays "Appsmith v1.10.0".
|
||||
This is because Appsmith Cloud doesn't support business features yet.
|
||||
*/
|
||||
export const APPSMITH_DISPLAY_VERSION = (
|
||||
|
|
@ -1244,3 +1244,11 @@ export const GENERATE_PAGE = () => "Generate page from data table";
|
|||
export const GENERATE_PAGE_DESCRIPTION = () =>
|
||||
"Start app with a simple CRUD UI and customize it";
|
||||
export const ADD_PAGE_FROM_TEMPLATE = () => "Add Page From Template";
|
||||
|
||||
// Alert options and labels for showMessage types
|
||||
export const ALERT_STYLE_OPTIONS = [
|
||||
{ label: "Info", value: "'info'", id: "info" },
|
||||
{ label: "Success", value: "'success'", id: "success" },
|
||||
{ label: "Error", value: "'error'", id: "error" },
|
||||
{ label: "Warning", value: "'warning'", id: "warning" },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
jest.mock("sagas/ActionExecution/NavigateActionSaga", () => ({
|
||||
__esModule: true,
|
||||
default: "",
|
||||
NavigationTargetType: { SAME_WINDOW: "" },
|
||||
}));
|
||||
|
||||
import { argsStringToArray } from "./Fields";
|
||||
|
||||
describe("Test argStringToArray", () => {
|
||||
const cases = [
|
||||
{ index: 0, input: "", expected: [""] },
|
||||
{ index: 1, input: "'a'", expected: ["'a'"] },
|
||||
{ index: 2, input: "a", expected: ["a"] },
|
||||
{ index: 3, input: "'a,b,c'", expected: ["'a,b,c'"] },
|
||||
{ index: 4, input: "a,b,c", expected: ["a", "b", "c"] },
|
||||
{ index: 5, input: "a, b, c", expected: ["a", " b", " c"] },
|
||||
{ index: 6, input: "a , b , c", expected: ["a ", " b ", " c"] },
|
||||
{ index: 7, input: "a\n,\nb,\nc", expected: ["a\n", "\nb", "\nc"] },
|
||||
{ index: 8, input: "[a,b,c]", expected: ["[a,b,c]"] },
|
||||
{ index: 9, input: "[a, b, c]", expected: ["[a, b, c]"] },
|
||||
{
|
||||
index: 10,
|
||||
input: "[\n\ta,\n\tb,\n\tc\n]",
|
||||
expected: ["[\n\ta,\n\tb,\n\tc\n]"],
|
||||
},
|
||||
{ index: 11, input: "{a:1,b:2,c:3}", expected: ["{a:1,b:2,c:3}"] },
|
||||
{
|
||||
index: 12,
|
||||
input: '{"a":1,"b":2,"c":3}',
|
||||
expected: ['{"a":1,"b":2,"c":3}'],
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
input: "{\n\ta:1,\n\tb:2,\n\tc:3}",
|
||||
expected: ["{\n\ta:1,\n\tb:2,\n\tc:3}"],
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
input: "()=>{}",
|
||||
expected: ["()=>{}"],
|
||||
},
|
||||
{
|
||||
index: 15,
|
||||
input: "(a, b)=>{return a+b}",
|
||||
expected: ["(a, b)=>{return a+b}"],
|
||||
},
|
||||
{
|
||||
index: 16,
|
||||
input: "(a, b)=>{\n\treturn a+b;\n\t}",
|
||||
expected: ["(a, b)=>{\n\treturn a+b;\n\t}"],
|
||||
},
|
||||
{
|
||||
index: 17,
|
||||
input: "(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}",
|
||||
expected: ["(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}"],
|
||||
},
|
||||
{
|
||||
index: 18,
|
||||
input: `() => {return 5}`,
|
||||
expected: ["() => {return 5}"],
|
||||
},
|
||||
{
|
||||
index: 19,
|
||||
input: `(a) => {return a + 1}`,
|
||||
expected: ["(a) => {return a + 1}"],
|
||||
},
|
||||
{
|
||||
index: 20,
|
||||
input: `(a, b) => {return a + b}`,
|
||||
expected: ["(a, b) => {return a + b}"],
|
||||
},
|
||||
];
|
||||
test.each(cases.map((x) => [x.index, x.input, x.expected]))(
|
||||
"test case %d",
|
||||
(_, input, expected) => {
|
||||
const result = argsStringToArray(input as string);
|
||||
expect(result).toStrictEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
import React from "react";
|
||||
|
||||
import {
|
||||
TreeDropdown,
|
||||
Setter,
|
||||
TreeDropdownOption,
|
||||
Switcher,
|
||||
SwitcherProps,
|
||||
} from "design-system";
|
||||
import {
|
||||
ControlWrapper,
|
||||
|
|
@ -16,7 +14,6 @@ import {
|
|||
} from "components/propertyControls/StyledControls";
|
||||
import { KeyValueComponent } from "components/propertyControls/KeyValueComponent";
|
||||
import { InputText } from "components/propertyControls/InputTextControl";
|
||||
import { getDynamicBindings, isDynamicValue } from "utils/DynamicBindingUtils";
|
||||
import HightlightedCode from "components/editorComponents/HighlightedCode";
|
||||
import { Skin } from "constants/DefaultTheme";
|
||||
import { DropdownOption } from "components/constants";
|
||||
|
|
@ -26,13 +23,33 @@ import DividerComponent from "widgets/DividerWidget/component";
|
|||
import store from "store";
|
||||
import { getPageList } from "selectors/entitiesSelector";
|
||||
import {
|
||||
APPSMITH_GLOBAL_FUNCTIONS,
|
||||
APPSMITH_NAMESPACED_FUNCTIONS,
|
||||
RESET_CHILDREN_OPTIONS,
|
||||
FILE_TYPE_OPTIONS,
|
||||
NAVIGATION_TARGET_FIELD_OPTIONS,
|
||||
ViewTypes,
|
||||
AppsmithFunction,
|
||||
FieldType,
|
||||
} from "./constants";
|
||||
import { PopoverPosition } from "@blueprintjs/core";
|
||||
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
/* TODO: Function and object types need to be updated to enable the lint rule */
|
||||
import { ACTION_TRIGGER_REGEX } from "./regex";
|
||||
import {
|
||||
SwitchType,
|
||||
ActionType,
|
||||
SelectorViewProps,
|
||||
KeyValueViewProps,
|
||||
TextViewProps,
|
||||
TabViewProps,
|
||||
FieldConfigs,
|
||||
} from "./types";
|
||||
import {
|
||||
modalSetter,
|
||||
modalGetter,
|
||||
textSetter,
|
||||
textGetter,
|
||||
enumTypeSetter,
|
||||
enumTypeGetter,
|
||||
} from "./utils";
|
||||
import { ALERT_STYLE_OPTIONS } from "../../../ce/constants/messages";
|
||||
|
||||
/**
|
||||
******** Steps to add a new function *******
|
||||
|
|
@ -54,234 +71,6 @@ import { PopoverPosition } from "@blueprintjs/core";
|
|||
* 2. Attach fields to the new action in the getFieldFromValue function
|
||||
**/
|
||||
|
||||
type Switch = {
|
||||
id: string;
|
||||
text: string;
|
||||
action: () => void;
|
||||
};
|
||||
|
||||
const ALERT_STYLE_OPTIONS = [
|
||||
{ label: "Info", value: "'info'", id: "info" },
|
||||
{ label: "Success", value: "'success'", id: "success" },
|
||||
{ label: "Error", value: "'error'", id: "error" },
|
||||
{ label: "Warning", value: "'warning'", id: "warning" },
|
||||
];
|
||||
|
||||
const RESET_CHILDREN_OPTIONS = [
|
||||
{ label: "true", value: "true", id: "true" },
|
||||
{ label: "false", value: "false", id: "false" },
|
||||
];
|
||||
|
||||
const FILE_TYPE_OPTIONS = [
|
||||
{ label: "Select file type (optional)", value: "", id: "" },
|
||||
{ label: "Plain text", value: "'text/plain'", id: "text/plain" },
|
||||
{ label: "HTML", value: "'text/html'", id: "text/html" },
|
||||
{ label: "CSV", value: "'text/csv'", id: "text/csv" },
|
||||
{ label: "JSON", value: "'application/json'", id: "application/json" },
|
||||
{ label: "JPEG", value: "'image/jpeg'", id: "image/jpeg" },
|
||||
{ label: "PNG", value: "'image/png'", id: "image/png" },
|
||||
{ label: "SVG", value: "'image/svg+xml'", id: "image/svg+xml" },
|
||||
];
|
||||
|
||||
const NAVIGATION_TARGET_FIELD_OPTIONS = [
|
||||
{
|
||||
label: "Same window",
|
||||
value: `'${NavigationTargetType.SAME_WINDOW}'`,
|
||||
id: NavigationTargetType.SAME_WINDOW,
|
||||
},
|
||||
{
|
||||
label: "New window",
|
||||
value: `'${NavigationTargetType.NEW_WINDOW}'`,
|
||||
id: NavigationTargetType.NEW_WINDOW,
|
||||
},
|
||||
];
|
||||
|
||||
export const FUNC_ARGS_REGEX = /((["][^"]*["])|([\[][\s\S]*[\]])|([\{][\s\S]*[\}])|(['][^']*['])|([\(][\s\S]*[\)][ ]*=>[ ]*[{][\s\S]*[}])|([^'",][^,"+]*[^'",]*))*/gi;
|
||||
export const ACTION_TRIGGER_REGEX = /^{{([\s\S]*?)\(([\s\S]*?)\)}}$/g;
|
||||
//Old Regex:: /\(\) => ([\s\S]*?)(\([\s\S]*?\))/g;
|
||||
export const ACTION_ANONYMOUS_FUNC_REGEX = /\(\) => (({[\s\S]*?})|([\s\S]*?)(\([\s\S]*?\)))/g;
|
||||
export const IS_URL_OR_MODAL = /^'.*'$/;
|
||||
const modalSetter = (changeValue: any, currentValue: string) => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = matches[0][2].split(",");
|
||||
if (isDynamicValue(changeValue)) {
|
||||
args[0] = `${changeValue.substring(2, changeValue.length - 2)}`;
|
||||
} else {
|
||||
args[0] = `'${changeValue}'`;
|
||||
}
|
||||
}
|
||||
return currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
};
|
||||
|
||||
export const modalGetter = (value: string) => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let name = "none";
|
||||
if (matches.length) {
|
||||
const modalName = matches[0][2].split(",")[0];
|
||||
if (IS_URL_OR_MODAL.test(modalName) || modalName === "") {
|
||||
name = modalName.substring(1, modalName.length - 1);
|
||||
} else {
|
||||
name = `{{${modalName}}}`;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
export const stringToJS = (string: string): string => {
|
||||
const { jsSnippets, stringSegments } = getDynamicBindings(string);
|
||||
const js = stringSegments
|
||||
.map((segment, index) => {
|
||||
if (jsSnippets[index] && jsSnippets[index].length > 0) {
|
||||
return jsSnippets[index];
|
||||
} else {
|
||||
return `'${segment}'`;
|
||||
}
|
||||
})
|
||||
.join(" + ");
|
||||
return js;
|
||||
};
|
||||
|
||||
export const JSToString = (js: string): string => {
|
||||
const segments = js.split(" + ");
|
||||
return segments
|
||||
.map((segment) => {
|
||||
if (segment.charAt(0) === "'") {
|
||||
return segment.substring(1, segment.length - 1);
|
||||
} else return "{{" + segment + "}}";
|
||||
})
|
||||
.join("");
|
||||
};
|
||||
|
||||
export const argsStringToArray = (funcArgs: string): string[] => {
|
||||
const argsplitMatches = [...funcArgs.matchAll(FUNC_ARGS_REGEX)];
|
||||
const arr: string[] = [];
|
||||
let isPrevUndefined = true;
|
||||
argsplitMatches.forEach((match) => {
|
||||
const matchVal = match[0];
|
||||
if (!matchVal || matchVal === "") {
|
||||
if (isPrevUndefined) {
|
||||
arr.push(matchVal);
|
||||
}
|
||||
isPrevUndefined = true;
|
||||
} else {
|
||||
isPrevUndefined = false;
|
||||
arr.push(matchVal);
|
||||
}
|
||||
});
|
||||
return arr;
|
||||
};
|
||||
|
||||
const textSetter = (
|
||||
changeValue: any,
|
||||
currentValue: string,
|
||||
argNum: number,
|
||||
): string => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = argsStringToArray(matches[0][2]);
|
||||
const jsVal = stringToJS(changeValue);
|
||||
args[argNum] = jsVal;
|
||||
}
|
||||
const result = currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
const textGetter = (value: string, argNum: number) => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
if (matches.length) {
|
||||
const args = argsStringToArray(matches[0][2]);
|
||||
const arg = args[argNum];
|
||||
const stringFromJS = arg ? JSToString(arg.trim()) : arg;
|
||||
return stringFromJS;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const enumTypeSetter = (
|
||||
changeValue: any,
|
||||
currentValue: string,
|
||||
argNum: number,
|
||||
): string => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = argsStringToArray(matches[0][2]);
|
||||
args[argNum] = changeValue as string;
|
||||
}
|
||||
const result = currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
const enumTypeGetter = (
|
||||
value: string,
|
||||
argNum: number,
|
||||
defaultValue = "",
|
||||
): string => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
if (matches.length) {
|
||||
const args = argsStringToArray(matches[0][2]);
|
||||
const arg = args[argNum];
|
||||
return arg ? arg.trim() : defaultValue;
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
export const ActionType = {
|
||||
none: "none",
|
||||
integration: "integration",
|
||||
jsFunction: "jsFunction",
|
||||
...APPSMITH_GLOBAL_FUNCTIONS,
|
||||
...APPSMITH_NAMESPACED_FUNCTIONS,
|
||||
};
|
||||
|
||||
type ActionType = typeof ActionType[keyof typeof ActionType];
|
||||
|
||||
const ViewTypes = {
|
||||
SELECTOR_VIEW: "SELECTOR_VIEW",
|
||||
KEY_VALUE_VIEW: "KEY_VALUE_VIEW",
|
||||
TEXT_VIEW: "TEXT_VIEW",
|
||||
BOOL_VIEW: "BOOL_VIEW",
|
||||
TAB_VIEW: "TAB_VIEW",
|
||||
};
|
||||
type ViewTypes = typeof ViewTypes[keyof typeof ViewTypes];
|
||||
|
||||
type ViewProps = {
|
||||
label: string;
|
||||
get: Function;
|
||||
set: Function;
|
||||
value: string;
|
||||
};
|
||||
type SelectorViewProps = ViewProps & {
|
||||
options: TreeDropdownOption[];
|
||||
defaultText: string;
|
||||
getDefaults?: (value?: any) => any;
|
||||
displayValue?: string;
|
||||
selectedLabelModifier?: (
|
||||
option: TreeDropdownOption,
|
||||
displayValue?: string,
|
||||
) => React.ReactNode;
|
||||
index?: number;
|
||||
};
|
||||
|
||||
type KeyValueViewProps = ViewProps;
|
||||
type TextViewProps = ViewProps & {
|
||||
index?: number;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
};
|
||||
type TabViewProps = Omit<ViewProps, "get" | "set"> & SwitcherProps;
|
||||
|
||||
const views = {
|
||||
[ViewTypes.SELECTOR_VIEW]: function SelectorView(props: SelectorViewProps) {
|
||||
return (
|
||||
|
|
@ -357,46 +146,6 @@ const views = {
|
|||
},
|
||||
};
|
||||
|
||||
export enum FieldType {
|
||||
ACTION_SELECTOR_FIELD = "ACTION_SELECTOR_FIELD",
|
||||
JS_ACTION_SELECTOR_FIELD = "JS_ACTION_SELECTOR_FIELD",
|
||||
ON_SUCCESS_FIELD = "ON_SUCCESS_FIELD",
|
||||
ON_ERROR_FIELD = "ON_ERROR_FIELD",
|
||||
SHOW_MODAL_FIELD = "SHOW_MODAL_FIELD",
|
||||
CLOSE_MODAL_FIELD = "CLOSE_MODAL_FIELD",
|
||||
PAGE_SELECTOR_FIELD = "PAGE_SELECTOR_FIELD",
|
||||
KEY_VALUE_FIELD = "KEY_VALUE_FIELD",
|
||||
URL_FIELD = "URL_FIELD",
|
||||
ALERT_TEXT_FIELD = "ALERT_TEXT_FIELD",
|
||||
ALERT_TYPE_SELECTOR_FIELD = "ALERT_TYPE_SELECTOR_FIELD",
|
||||
KEY_TEXT_FIELD = "KEY_TEXT_FIELD",
|
||||
VALUE_TEXT_FIELD = "VALUE_TEXT_FIELD",
|
||||
QUERY_PARAMS_FIELD = "QUERY_PARAMS_FIELD",
|
||||
DOWNLOAD_DATA_FIELD = "DOWNLOAD_DATA_FIELD",
|
||||
DOWNLOAD_FILE_NAME_FIELD = "DOWNLOAD_FILE_NAME_FIELD",
|
||||
DOWNLOAD_FILE_TYPE_FIELD = "DOWNLOAD_FILE_TYPE_FIELD",
|
||||
COPY_TEXT_FIELD = "COPY_TEXT_FIELD",
|
||||
NAVIGATION_TARGET_FIELD = "NAVIGATION_TARGET_FIELD",
|
||||
WIDGET_NAME_FIELD = "WIDGET_NAME_FIELD",
|
||||
RESET_CHILDREN_FIELD = "RESET_CHILDREN_FIELD",
|
||||
ARGUMENT_KEY_VALUE_FIELD = "ARGUMENT_KEY_VALUE_FIELD",
|
||||
CALLBACK_FUNCTION_FIELD = "CALLBACK_FUNCTION_FIELD",
|
||||
DELAY_FIELD = "DELAY_FIELD",
|
||||
ID_FIELD = "ID_FIELD",
|
||||
CLEAR_INTERVAL_ID_FIELD = "CLEAR_INTERVAL_ID_FIELD",
|
||||
MESSAGE_FIELD = "MESSAGE_FIELD",
|
||||
TARGET_ORIGIN_FIELD = "TARGET_ORIGIN_FIELD",
|
||||
PAGE_NAME_AND_URL_TAB_SELECTOR_FIELD = "PAGE_NAME_AND_URL_TAB_SELECTOR_FIELD",
|
||||
}
|
||||
|
||||
type FieldConfig = {
|
||||
getter: Function;
|
||||
setter: Function;
|
||||
view: ViewTypes;
|
||||
};
|
||||
|
||||
type FieldConfigs = Partial<Record<FieldType, FieldConfig>>;
|
||||
|
||||
const fieldConfigs: FieldConfigs = {
|
||||
[FieldType.ACTION_SELECTOR_FIELD]: {
|
||||
getter: (storedValue: string) => {
|
||||
|
|
@ -406,9 +155,9 @@ const fieldConfigs: FieldConfigs = {
|
|||
? [...storedValue.matchAll(ACTION_TRIGGER_REGEX)]
|
||||
: [];
|
||||
}
|
||||
let mainFuncSelectedValue = ActionType.none;
|
||||
let mainFuncSelectedValue = AppsmithFunction.none;
|
||||
if (matches.length) {
|
||||
mainFuncSelectedValue = matches[0][1] || ActionType.none;
|
||||
mainFuncSelectedValue = matches[0][1] || AppsmithFunction.none;
|
||||
}
|
||||
const mainFuncSelectedValueSplit = mainFuncSelectedValue.split(".");
|
||||
if (mainFuncSelectedValueSplit[1] === "run") {
|
||||
|
|
@ -422,22 +171,22 @@ const fieldConfigs: FieldConfigs = {
|
|||
let defaultParams = "";
|
||||
let defaultArgs: Array<any> = [];
|
||||
switch (type) {
|
||||
case ActionType.integration:
|
||||
case AppsmithFunction.integration:
|
||||
value = `${value}.run`;
|
||||
break;
|
||||
case ActionType.navigateTo:
|
||||
case AppsmithFunction.navigateTo:
|
||||
defaultParams = `'', {}, 'SAME_WINDOW'`;
|
||||
break;
|
||||
case ActionType.jsFunction:
|
||||
case AppsmithFunction.jsFunction:
|
||||
defaultArgs = option.args ? option.args : [];
|
||||
break;
|
||||
case ActionType.setInterval:
|
||||
case AppsmithFunction.setInterval:
|
||||
defaultParams = "() => { \n\t // add code here \n}, 5000";
|
||||
break;
|
||||
case ActionType.getGeolocation:
|
||||
case AppsmithFunction.getGeolocation:
|
||||
defaultParams = "(location) => { \n\t // add code here \n }";
|
||||
break;
|
||||
case ActionType.resetWidget:
|
||||
case AppsmithFunction.resetWidget:
|
||||
defaultParams = `"",true`;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -687,7 +436,7 @@ const fieldConfigs: FieldConfigs = {
|
|||
};
|
||||
|
||||
function renderField(props: {
|
||||
onValueChange: Function;
|
||||
onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
|
||||
value: string;
|
||||
field: { field: FieldType; value: string; label: string; index: number };
|
||||
label?: string;
|
||||
|
|
@ -698,8 +447,8 @@ function renderField(props: {
|
|||
depth: number;
|
||||
maxDepth: number;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
activeNavigateToTab: Switch;
|
||||
navigateToSwitches: Array<Switch>;
|
||||
activeNavigateToTab: SwitchType;
|
||||
navigateToSwitches: Array<SwitchType>;
|
||||
}) {
|
||||
const { field } = props;
|
||||
const fieldType = field.field;
|
||||
|
|
@ -739,7 +488,7 @@ function renderField(props: {
|
|||
option: TreeDropdownOption,
|
||||
displayValue?: string,
|
||||
) {
|
||||
if (option.type === ActionType.integration) {
|
||||
if (option.type === AppsmithFunction.integration) {
|
||||
return (
|
||||
<HightlightedCode
|
||||
codeText={`{{${option.label}.run()}}`}
|
||||
|
|
@ -755,7 +504,7 @@ function renderField(props: {
|
|||
};
|
||||
getDefaults = (value: string) => {
|
||||
return {
|
||||
[ActionType.navigateTo]: `'${props.pageDropdownOptions[0].label}'`,
|
||||
[AppsmithFunction.navigateTo]: `'${props.pageDropdownOptions[0].label}'`,
|
||||
}[value];
|
||||
};
|
||||
}
|
||||
|
|
@ -838,7 +587,7 @@ function renderField(props: {
|
|||
props.value,
|
||||
props.field.index,
|
||||
);
|
||||
props.onValueChange(finalValueToSet);
|
||||
props.onValueChange(finalValueToSet, false);
|
||||
},
|
||||
index: props.field.index,
|
||||
value: props.value || "",
|
||||
|
|
@ -851,7 +600,7 @@ function renderField(props: {
|
|||
get: fieldConfig.getter,
|
||||
set: (value: string | DropdownOption) => {
|
||||
const finalValueToSet = fieldConfig.setter(value, props.value);
|
||||
props.onValueChange(finalValueToSet);
|
||||
props.onValueChange(finalValueToSet, false);
|
||||
},
|
||||
value: props.value,
|
||||
defaultText: "Select Action",
|
||||
|
|
@ -918,7 +667,7 @@ function renderField(props: {
|
|||
}
|
||||
|
||||
function Fields(props: {
|
||||
onValueChange: Function;
|
||||
onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
|
||||
value: string;
|
||||
fields: any;
|
||||
label?: string;
|
||||
|
|
@ -929,8 +678,8 @@ function Fields(props: {
|
|||
depth: number;
|
||||
maxDepth: number;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
navigateToSwitches: Array<Switch>;
|
||||
activeNavigateToTab: Switch;
|
||||
navigateToSwitches: Array<SwitchType>;
|
||||
activeNavigateToTab: SwitchType;
|
||||
}) {
|
||||
const { fields, ...otherProps } = props;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,3 +16,85 @@ export const APPSMITH_NAMESPACED_FUNCTIONS = {
|
|||
watchGeolocation: "appsmith.geolocation.watchPosition",
|
||||
stopWatchGeolocation: "appsmith.geolocation.clearWatch",
|
||||
};
|
||||
|
||||
export const AppsmithFunction = {
|
||||
none: "none",
|
||||
integration: "integration",
|
||||
jsFunction: "jsFunction",
|
||||
...APPSMITH_GLOBAL_FUNCTIONS,
|
||||
...APPSMITH_NAMESPACED_FUNCTIONS,
|
||||
};
|
||||
|
||||
export const RESET_CHILDREN_OPTIONS = [
|
||||
{ label: "true", value: "true", id: "true" },
|
||||
{ label: "false", value: "false", id: "false" },
|
||||
];
|
||||
|
||||
export const FILE_TYPE_OPTIONS = [
|
||||
{ label: "Select file type (optional)", value: "", id: "" },
|
||||
{ label: "Plain text", value: "'text/plain'", id: "text/plain" },
|
||||
{ label: "HTML", value: "'text/html'", id: "text/html" },
|
||||
{ label: "CSV", value: "'text/csv'", id: "text/csv" },
|
||||
{ label: "JSON", value: "'application/json'", id: "application/json" },
|
||||
{ label: "JPEG", value: "'image/jpeg'", id: "image/jpeg" },
|
||||
{ label: "PNG", value: "'image/png'", id: "image/png" },
|
||||
{ label: "SVG", value: "'image/svg+xml'", id: "image/svg+xml" },
|
||||
];
|
||||
|
||||
export const NAVIGATION_TARGET_FIELD_OPTIONS = [
|
||||
{
|
||||
label: "Same window",
|
||||
value: "SAME_WINDOW",
|
||||
id: "SAME_WINDOW",
|
||||
},
|
||||
{
|
||||
label: "New window",
|
||||
value: "NEW_WINDOW",
|
||||
id: "NEW_WINDOW",
|
||||
},
|
||||
];
|
||||
|
||||
export const ViewTypes = {
|
||||
SELECTOR_VIEW: "SELECTOR_VIEW",
|
||||
KEY_VALUE_VIEW: "KEY_VALUE_VIEW",
|
||||
TEXT_VIEW: "TEXT_VIEW",
|
||||
BOOL_VIEW: "BOOL_VIEW",
|
||||
TAB_VIEW: "TAB_VIEW",
|
||||
};
|
||||
|
||||
export const NAVIGATE_TO_TAB_OPTIONS = {
|
||||
PAGE_NAME: "page-name",
|
||||
URL: "url",
|
||||
};
|
||||
|
||||
export enum FieldType {
|
||||
ACTION_SELECTOR_FIELD = "ACTION_SELECTOR_FIELD",
|
||||
JS_ACTION_SELECTOR_FIELD = "JS_ACTION_SELECTOR_FIELD",
|
||||
ON_SUCCESS_FIELD = "ON_SUCCESS_FIELD",
|
||||
ON_ERROR_FIELD = "ON_ERROR_FIELD",
|
||||
SHOW_MODAL_FIELD = "SHOW_MODAL_FIELD",
|
||||
CLOSE_MODAL_FIELD = "CLOSE_MODAL_FIELD",
|
||||
PAGE_SELECTOR_FIELD = "PAGE_SELECTOR_FIELD",
|
||||
KEY_VALUE_FIELD = "KEY_VALUE_FIELD",
|
||||
URL_FIELD = "URL_FIELD",
|
||||
ALERT_TEXT_FIELD = "ALERT_TEXT_FIELD",
|
||||
ALERT_TYPE_SELECTOR_FIELD = "ALERT_TYPE_SELECTOR_FIELD",
|
||||
KEY_TEXT_FIELD = "KEY_TEXT_FIELD",
|
||||
VALUE_TEXT_FIELD = "VALUE_TEXT_FIELD",
|
||||
QUERY_PARAMS_FIELD = "QUERY_PARAMS_FIELD",
|
||||
DOWNLOAD_DATA_FIELD = "DOWNLOAD_DATA_FIELD",
|
||||
DOWNLOAD_FILE_NAME_FIELD = "DOWNLOAD_FILE_NAME_FIELD",
|
||||
DOWNLOAD_FILE_TYPE_FIELD = "DOWNLOAD_FILE_TYPE_FIELD",
|
||||
COPY_TEXT_FIELD = "COPY_TEXT_FIELD",
|
||||
NAVIGATION_TARGET_FIELD = "NAVIGATION_TARGET_FIELD",
|
||||
WIDGET_NAME_FIELD = "WIDGET_NAME_FIELD",
|
||||
RESET_CHILDREN_FIELD = "RESET_CHILDREN_FIELD",
|
||||
ARGUMENT_KEY_VALUE_FIELD = "ARGUMENT_KEY_VALUE_FIELD",
|
||||
CALLBACK_FUNCTION_FIELD = "CALLBACK_FUNCTION_FIELD",
|
||||
DELAY_FIELD = "DELAY_FIELD",
|
||||
ID_FIELD = "ID_FIELD",
|
||||
CLEAR_INTERVAL_ID_FIELD = "CLEAR_INTERVAL_ID_FIELD",
|
||||
MESSAGE_FIELD = "MESSAGE_FIELD",
|
||||
TARGET_ORIGIN_FIELD = "TARGET_ORIGIN_FIELD",
|
||||
PAGE_NAME_AND_URL_TAB_SELECTOR_FIELD = "PAGE_NAME_AND_URL_TAB_SELECTOR_FIELD",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,7 @@ import {
|
|||
getModalDropdownList,
|
||||
getNextModalName,
|
||||
} from "selectors/widgetSelectors";
|
||||
import Fields, {
|
||||
ACTION_ANONYMOUS_FUNC_REGEX,
|
||||
ACTION_TRIGGER_REGEX,
|
||||
ActionType,
|
||||
FieldType,
|
||||
} from "./Fields";
|
||||
import Fields from "./Fields";
|
||||
import { getDataTree } from "selectors/dataTreeSelectors";
|
||||
import { DataTree, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import { getEntityNameAndPropertyPath } from "workers/evaluationUtils";
|
||||
|
|
@ -62,69 +57,74 @@ import { selectFeatureFlags } from "selectors/usersSelectors";
|
|||
import FeatureFlags from "entities/FeatureFlags";
|
||||
import { connect } from "react-redux";
|
||||
import { isValidURL } from "utils/URLUtils";
|
||||
import { ACTION_ANONYMOUS_FUNC_REGEX, ACTION_TRIGGER_REGEX } from "./regex";
|
||||
import {
|
||||
NAVIGATE_TO_TAB_OPTIONS,
|
||||
AppsmithFunction,
|
||||
FieldType,
|
||||
} from "./constants";
|
||||
import { SwitchType, ActionCreatorProps, GenericFunction } from "./types";
|
||||
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
/* TODO: Function and object types need to be updated to enable the lint rule */
|
||||
const baseOptions: { label: string; value: string }[] = [
|
||||
{
|
||||
label: createMessage(NO_ACTION),
|
||||
value: ActionType.none,
|
||||
value: AppsmithFunction.none,
|
||||
},
|
||||
{
|
||||
label: createMessage(EXECUTE_A_QUERY),
|
||||
value: ActionType.integration,
|
||||
value: AppsmithFunction.integration,
|
||||
},
|
||||
{
|
||||
label: createMessage(NAVIGATE_TO),
|
||||
value: ActionType.navigateTo,
|
||||
value: AppsmithFunction.navigateTo,
|
||||
},
|
||||
{
|
||||
label: createMessage(SHOW_MESSAGE),
|
||||
value: ActionType.showAlert,
|
||||
value: AppsmithFunction.showAlert,
|
||||
},
|
||||
{
|
||||
label: createMessage(OPEN_MODAL),
|
||||
value: ActionType.showModal,
|
||||
value: AppsmithFunction.showModal,
|
||||
},
|
||||
{
|
||||
label: createMessage(CLOSE_MODAL),
|
||||
value: ActionType.closeModal,
|
||||
value: AppsmithFunction.closeModal,
|
||||
},
|
||||
{
|
||||
label: createMessage(STORE_VALUE),
|
||||
value: ActionType.storeValue,
|
||||
value: AppsmithFunction.storeValue,
|
||||
},
|
||||
{
|
||||
label: createMessage(DOWNLOAD),
|
||||
value: ActionType.download,
|
||||
value: AppsmithFunction.download,
|
||||
},
|
||||
{
|
||||
label: createMessage(COPY_TO_CLIPBOARD),
|
||||
value: ActionType.copyToClipboard,
|
||||
value: AppsmithFunction.copyToClipboard,
|
||||
},
|
||||
{
|
||||
label: createMessage(RESET_WIDGET),
|
||||
value: ActionType.resetWidget,
|
||||
value: AppsmithFunction.resetWidget,
|
||||
},
|
||||
{
|
||||
label: createMessage(SET_INTERVAL),
|
||||
value: ActionType.setInterval,
|
||||
value: AppsmithFunction.setInterval,
|
||||
},
|
||||
{
|
||||
label: createMessage(CLEAR_INTERVAL),
|
||||
value: ActionType.clearInterval,
|
||||
value: AppsmithFunction.clearInterval,
|
||||
},
|
||||
{
|
||||
label: createMessage(GET_GEO_LOCATION),
|
||||
value: ActionType.getGeolocation,
|
||||
value: AppsmithFunction.getGeolocation,
|
||||
},
|
||||
{
|
||||
label: createMessage(WATCH_GEO_LOCATION),
|
||||
value: ActionType.watchGeolocation,
|
||||
value: AppsmithFunction.watchGeolocation,
|
||||
},
|
||||
{
|
||||
label: createMessage(STOP_WATCH_GEO_LOCATION),
|
||||
value: ActionType.stopWatchGeolocation,
|
||||
value: AppsmithFunction.stopWatchGeolocation,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -132,28 +132,22 @@ const getBaseOptions = (featureFlags: FeatureFlags) => {
|
|||
const { JS_EDITOR: isJSEditorEnabled } = featureFlags;
|
||||
if (isJSEditorEnabled) {
|
||||
const jsOption = baseOptions.find(
|
||||
(option: any) => option.value === ActionType.jsFunction,
|
||||
(option: any) => option.value === AppsmithFunction.jsFunction,
|
||||
);
|
||||
if (!jsOption) {
|
||||
baseOptions.splice(2, 0, {
|
||||
label: createMessage(EXECUTE_JS_FUNCTION),
|
||||
value: ActionType.jsFunction,
|
||||
value: AppsmithFunction.jsFunction,
|
||||
});
|
||||
}
|
||||
}
|
||||
return baseOptions;
|
||||
};
|
||||
|
||||
type Switch = {
|
||||
id: string;
|
||||
text: string;
|
||||
action: () => void;
|
||||
};
|
||||
|
||||
function getFieldFromValue(
|
||||
value: string | undefined,
|
||||
activeTabNavigateTo: Switch,
|
||||
getParentValue?: Function,
|
||||
activeTabNavigateTo: SwitchType,
|
||||
getParentValue?: (changeValue: string) => string,
|
||||
dataTree?: DataTree,
|
||||
): any[] {
|
||||
const fields: any[] = [];
|
||||
|
|
@ -408,7 +402,7 @@ function useModalDropdownList() {
|
|||
id: "create",
|
||||
icon: "plus",
|
||||
className: "t--create-modal-btn",
|
||||
onSelect: (option: TreeDropdownOption, setter?: Function) => {
|
||||
onSelect: (option: TreeDropdownOption, setter?: GenericFunction) => {
|
||||
const modalName = nextModalName;
|
||||
if (setter) {
|
||||
setter({
|
||||
|
|
@ -459,11 +453,11 @@ function getIntegrationOptionsWithChildren(
|
|||
action.config.pluginType === PluginType.REMOTE,
|
||||
);
|
||||
const option = options.find(
|
||||
(option) => option.value === ActionType.integration,
|
||||
(option) => option.value === AppsmithFunction.integration,
|
||||
);
|
||||
|
||||
const jsOption = options.find(
|
||||
(option) => option.value === ActionType.jsFunction,
|
||||
(option) => option.value === AppsmithFunction.jsFunction,
|
||||
);
|
||||
|
||||
if (option) {
|
||||
|
|
@ -586,18 +580,6 @@ function useIntegrationsOptionTree() {
|
|||
);
|
||||
}
|
||||
|
||||
type ActionCreatorProps = {
|
||||
value: string;
|
||||
onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
pageDropdownOptions: TreeDropdownOption[];
|
||||
};
|
||||
|
||||
const NAVIGATE_TO_TAB_OPTIONS = {
|
||||
PAGE_NAME: "page-name",
|
||||
URL: "url",
|
||||
};
|
||||
|
||||
const isValueValidURL = (value: string) => {
|
||||
if (value) {
|
||||
const indices = [];
|
||||
|
|
@ -613,7 +595,7 @@ const isValueValidURL = (value: string) => {
|
|||
|
||||
const ActionCreator = React.forwardRef(
|
||||
(props: ActionCreatorProps, ref: any) => {
|
||||
const NAVIGATE_TO_TAB_SWITCHER: Array<Switch> = [
|
||||
const NAVIGATE_TO_TAB_SWITCHER: Array<SwitchType> = [
|
||||
{
|
||||
id: "page-name",
|
||||
text: "Page Name",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
export const FUNC_ARGS_REGEX = /((["][^"]*["])|([\[][\s\S]*[\]])|([\{][\s\S]*[\}])|(['][^']*['])|([\(][\s\S]*[\)][ ]*=>[ ]*[{][\s\S]*[}])|([^'",][^,"+]*[^'",]*))*/gi;
|
||||
|
||||
//Old Regex:: /\(\) => ([\s\S]*?)(\([\s\S]*?\))/g;
|
||||
export const ACTION_TRIGGER_REGEX = /^{{([\s\S]*?)\(([\s\S]*?)\)}}$/g;
|
||||
|
||||
export const ACTION_ANONYMOUS_FUNC_REGEX = /\(\) => (({[\s\S]*?})|([\s\S]*?)(\([\s\S]*?\)))/g;
|
||||
|
||||
export const IS_URL_OR_MODAL = /^'.*'$/;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { SwitcherProps, TreeDropdownOption } from "design-system";
|
||||
import React from "react";
|
||||
import { FieldType, ViewTypes, AppsmithFunction } from "./constants";
|
||||
|
||||
export type GenericFunction = (...args: any[]) => any;
|
||||
|
||||
export type SwitchType = {
|
||||
id: string;
|
||||
text: string;
|
||||
action: () => void;
|
||||
};
|
||||
|
||||
export type ActionType = typeof AppsmithFunction[keyof typeof AppsmithFunction];
|
||||
|
||||
export type ViewType = typeof ViewTypes[keyof typeof ViewTypes];
|
||||
|
||||
export type ViewProps = {
|
||||
label: string;
|
||||
get: GenericFunction;
|
||||
set: GenericFunction;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type SelectorViewProps = ViewProps & {
|
||||
options: TreeDropdownOption[];
|
||||
defaultText: string;
|
||||
getDefaults?: (value?: any) => any;
|
||||
displayValue?: string;
|
||||
selectedLabelModifier?: (
|
||||
option: TreeDropdownOption,
|
||||
displayValue?: string,
|
||||
) => React.ReactNode;
|
||||
index?: number;
|
||||
};
|
||||
|
||||
export type KeyValueViewProps = ViewProps;
|
||||
|
||||
export type TextViewProps = ViewProps & {
|
||||
index?: number;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
};
|
||||
|
||||
export type TabViewProps = Omit<ViewProps, "get" | "set"> & SwitcherProps;
|
||||
|
||||
export type FieldConfig = {
|
||||
getter: GenericFunction;
|
||||
setter: GenericFunction;
|
||||
view: ViewType;
|
||||
};
|
||||
|
||||
export type FieldConfigs = Partial<Record<FieldType, FieldConfig>>;
|
||||
|
||||
export type ActionCreatorProps = {
|
||||
value: string;
|
||||
onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
|
||||
additionalAutoComplete?: Record<string, Record<string, unknown>>;
|
||||
pageDropdownOptions: TreeDropdownOption[];
|
||||
};
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
jest.mock("sagas/ActionExecution/NavigateActionSaga", () => ({
|
||||
__esModule: true,
|
||||
default: "",
|
||||
NavigationTargetType: { SAME_WINDOW: "" },
|
||||
}));
|
||||
|
||||
import {
|
||||
argsStringToArray,
|
||||
enumTypeSetter,
|
||||
enumTypeGetter,
|
||||
JSToString,
|
||||
modalGetter,
|
||||
modalSetter,
|
||||
stringToJS,
|
||||
textGetter,
|
||||
textSetter,
|
||||
} from "./utils";
|
||||
|
||||
describe("Test argStringToArray", () => {
|
||||
const cases = [
|
||||
{ index: 0, input: "", expected: [""] },
|
||||
{ index: 1, input: "'a'", expected: ["'a'"] },
|
||||
{ index: 2, input: "a", expected: ["a"] },
|
||||
{ index: 3, input: "'a,b,c'", expected: ["'a,b,c'"] },
|
||||
{ index: 4, input: "a,b,c", expected: ["a", "b", "c"] },
|
||||
{ index: 5, input: "a, b, c", expected: ["a", " b", " c"] },
|
||||
{ index: 6, input: "a , b , c", expected: ["a ", " b ", " c"] },
|
||||
{ index: 7, input: "[a,b,c]", expected: ["[a,b,c]"] },
|
||||
{ index: 8, input: "[a, b, c]", expected: ["[a, b, c]"] },
|
||||
{
|
||||
index: 9,
|
||||
input: "[\n\ta,\n\tb,\n\tc\n]",
|
||||
expected: ["[\n\ta,\n\tb,\n\tc\n]"],
|
||||
},
|
||||
{ index: 10, input: "{a:1,b:2,c:3}", expected: ["{a:1,b:2,c:3}"] },
|
||||
{
|
||||
index: 11,
|
||||
input: '{"a":1,"b":2,"c":3}',
|
||||
expected: ['{"a":1,"b":2,"c":3}'],
|
||||
},
|
||||
{
|
||||
index: 12,
|
||||
input: "{\n\ta:1,\n\tb:2,\n\tc:3}",
|
||||
expected: ["{\n\ta:1,\n\tb:2,\n\tc:3}"],
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
input: "()=>{}",
|
||||
expected: ["()=>{}"],
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
input: "(a, b)=>{return a+b}",
|
||||
expected: ["(a, b)=>{return a+b}"],
|
||||
},
|
||||
{
|
||||
index: 15,
|
||||
input: "(a, b)=>{\n\treturn a+b;\n\t}",
|
||||
expected: ["(a, b)=>{\n\treturn a+b;\n\t}"],
|
||||
},
|
||||
{
|
||||
index: 16,
|
||||
input: "(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}",
|
||||
expected: ["(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}"],
|
||||
},
|
||||
{
|
||||
index: 17,
|
||||
input: `() => {return 5}`,
|
||||
expected: ["() => {return 5}"],
|
||||
},
|
||||
{
|
||||
index: 19,
|
||||
input: `(a) => {return a + 1}`,
|
||||
expected: ["(a) => {return a + 1}"],
|
||||
},
|
||||
{
|
||||
index: 19,
|
||||
input: `(a, b) => {return a + b}`,
|
||||
expected: ["(a, b) => {return a + b}"],
|
||||
},
|
||||
];
|
||||
test.each(cases.map((x) => [x.index, x.input, x.expected]))(
|
||||
"test case %d",
|
||||
(_, input, expected) => {
|
||||
const result = argsStringToArray(input as string);
|
||||
expect(result).toStrictEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("Test stringToJS", () => {
|
||||
const cases = [
|
||||
{ index: 1, input: "{{'a'}}", expected: "'a'" },
|
||||
{ index: 2, input: "{{a}}", expected: "a" },
|
||||
{ index: 3, input: "{{'a,b,c'}}", expected: "'a,b,c'" },
|
||||
{ index: 4, input: "{{a,b,c}}", expected: "a,b,c" },
|
||||
{ index: 5, input: "{{a, b, c}}", expected: "a, b, c" },
|
||||
{ index: 6, input: "{{a , b , c}}", expected: "a , b , c" },
|
||||
{ index: 7, input: "{{[a,b,c]}}", expected: "[a,b,c]" },
|
||||
{ index: 8, input: "{{[a, b, c]}}", expected: "[a, b, c]" },
|
||||
{
|
||||
index: 9,
|
||||
input: "{{[\n\ta,\n\tb,\n\tc\n]}}",
|
||||
expected: "[\n\ta,\n\tb,\n\tc\n]",
|
||||
},
|
||||
{ index: 10, input: "{{{a:1,b:2,c:3}}}", expected: "{a:1,b:2,c:3}" },
|
||||
{
|
||||
index: 11,
|
||||
input: '{{{"a":1,"b":2,"c":3}}}',
|
||||
expected: '{"a":1,"b":2,"c":3}',
|
||||
},
|
||||
{
|
||||
index: 12,
|
||||
input: "{{{\n\ta:1,\n\tb:2,\n\tc:3}}}",
|
||||
expected: "{\n\ta:1,\n\tb:2,\n\tc:3}",
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
input: "{{()=>{}}}",
|
||||
expected: "()=>{}",
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
input: "{{(a, b)=>{return a+b}}}",
|
||||
expected: "(a, b)=>{return a+b}",
|
||||
},
|
||||
{
|
||||
index: 15,
|
||||
input: "{{(a, b)=>{\n\treturn a+b;\n\t}}}",
|
||||
expected: "(a, b)=>{\n\treturn a+b;\n\t}",
|
||||
},
|
||||
{
|
||||
index: 16,
|
||||
input: "{{(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}}}",
|
||||
expected: "(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}",
|
||||
},
|
||||
{
|
||||
index: 17,
|
||||
input: "{{() => {return 5}}}",
|
||||
expected: "() => {return 5}",
|
||||
},
|
||||
{
|
||||
index: 18,
|
||||
input: "{{(a) => {return a + 1}}}",
|
||||
expected: "(a) => {return a + 1}",
|
||||
},
|
||||
{
|
||||
index: 19,
|
||||
input: "{{(a, b) => {return a + b}}}",
|
||||
expected: "(a, b) => {return a + b}",
|
||||
},
|
||||
];
|
||||
test.each(cases.map((x) => [x.index, x.input, x.expected]))(
|
||||
"test case %d",
|
||||
(_, input, expected) => {
|
||||
const result = stringToJS(input as string);
|
||||
expect(result).toStrictEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("Test JSToString", () => {
|
||||
const cases = [
|
||||
{ index: 1, input: "'a'", expected: "a" },
|
||||
{ index: 2, input: "a", expected: "{{a}}" },
|
||||
{ index: 3, input: "'a,b,c'", expected: "a,b,c" },
|
||||
{ index: 4, input: "a,b,c", expected: "{{a,b,c}}" },
|
||||
{ index: 5, input: "a, b, c", expected: "{{a, b, c}}" },
|
||||
{ index: 6, input: "a , b , c", expected: "{{a , b , c}}" },
|
||||
{ index: 7, input: "[a,b,c]", expected: "{{[a,b,c]}}" },
|
||||
{ index: 8, input: "[a, b, c]", expected: "{{[a, b, c]}}" },
|
||||
{
|
||||
index: 9,
|
||||
input: "[\n\ta,\n\tb,\n\tc\n]",
|
||||
expected: "{{[\n\ta,\n\tb,\n\tc\n]}}",
|
||||
},
|
||||
{ index: 10, input: "{a:1,b:2,c:3}", expected: "{{{a:1,b:2,c:3}}}" },
|
||||
{
|
||||
index: 11,
|
||||
input: '{"a":1,"b":2,"c":3}',
|
||||
expected: '{{{"a":1,"b":2,"c":3}}}',
|
||||
},
|
||||
{
|
||||
index: 12,
|
||||
input: "{\n\ta:1,\n\tb:2,\n\tc:3}",
|
||||
expected: "{{{\n\ta:1,\n\tb:2,\n\tc:3}}}",
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
input: "()=>{}",
|
||||
expected: "{{()=>{}}}",
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
input: "(a, b)=>{return a+b}",
|
||||
expected: "{{(a, b)=>{return a+b}}}",
|
||||
},
|
||||
{
|
||||
index: 15,
|
||||
input: "(a, b)=>{\n\treturn a+b;\n\t}",
|
||||
expected: "{{(a, b)=>{\n\treturn a+b;\n\t}}}",
|
||||
},
|
||||
{
|
||||
index: 16,
|
||||
input: "(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}",
|
||||
expected: "{{(\n\ta,\n\tb\n)=>{\n\treturn a+b;\n\t}}}",
|
||||
},
|
||||
{
|
||||
index: 17,
|
||||
input: "() => {return 5}",
|
||||
expected: "{{() => {return 5}}}",
|
||||
},
|
||||
];
|
||||
test.each(cases.map((x) => [x.index, x.input, x.expected]))(
|
||||
"test case %d",
|
||||
(_, input, expected) => {
|
||||
const result = JSToString(input as string);
|
||||
expect(result).toStrictEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("Test modalSetter", () => {
|
||||
const result = modalSetter("Modal1", "{{closeModal()}}");
|
||||
expect(result).toStrictEqual("{{closeModal('Modal1')}}");
|
||||
});
|
||||
|
||||
describe("Test modalGetter", () => {
|
||||
const result = modalGetter("{{showModal('Modal1')}}");
|
||||
expect(result).toStrictEqual("Modal1");
|
||||
});
|
||||
|
||||
describe("Test textSetter", () => {
|
||||
const result = textSetter(
|
||||
"google.com",
|
||||
"{{navigateTo('', {},NEW_WINDOW)}}",
|
||||
0,
|
||||
);
|
||||
expect(result).toStrictEqual("{{navigateTo('google.com', {},NEW_WINDOW)}}");
|
||||
});
|
||||
|
||||
describe("Test textGetter", () => {
|
||||
const cases = [
|
||||
{
|
||||
index: 0,
|
||||
input: "{{navigateTo('google.com', {}, NEW_WINDOW)}}",
|
||||
expected: "google.com",
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
input: "{{navigateTo('google.com', {}, NEW_WINDOW)}}",
|
||||
expected: "{{{}}}",
|
||||
},
|
||||
];
|
||||
test.each(cases.map((x) => [x.index, x.input, x.expected]))(
|
||||
"test case %d",
|
||||
(index, input, expected) => {
|
||||
const result = textGetter(input as string, index as number);
|
||||
expect(result).toStrictEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("Test enumTypeSetter", () => {
|
||||
const cases = [
|
||||
{
|
||||
index: 0,
|
||||
value: "info",
|
||||
input: "{{showAlert('hi')}}",
|
||||
expected: "{{showAlert('hi',info)}}",
|
||||
argNum: 1,
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
value: "info",
|
||||
input: "{{showAlert('hi','error')}}",
|
||||
expected: "{{showAlert('hi',info)}}",
|
||||
argNum: 1,
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
value: "info",
|
||||
input: "{{showAlert(,'')}}",
|
||||
expected: "{{showAlert(,info)}}",
|
||||
argNum: 1,
|
||||
},
|
||||
];
|
||||
test.each(
|
||||
cases.map((x) => [x.index, x.input, x.expected, x.value, x.argNum]),
|
||||
)("test case %d", (index, input, expected, value, argNum) => {
|
||||
const result = enumTypeSetter(
|
||||
value as string,
|
||||
input as string,
|
||||
argNum as number,
|
||||
);
|
||||
expect(result).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Test enumTypeGetter", () => {
|
||||
const cases = [
|
||||
{
|
||||
index: 0,
|
||||
value: "success",
|
||||
input: "{{showAlert('hi','info')}}",
|
||||
expected: "{{showAlert('hi','info')}}",
|
||||
argNum: 1,
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
value: "info",
|
||||
input: "{{showAlert(,'error')}}",
|
||||
expected: "{{showAlert(,'error')}}",
|
||||
argNum: 1,
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
value: "info",
|
||||
input: "{{showAlert()}}",
|
||||
expected: "{{showAlert()}}",
|
||||
argNum: 1,
|
||||
},
|
||||
];
|
||||
test.each(
|
||||
cases.map((x) => [x.index, x.input, x.expected, x.value, x.argNum]),
|
||||
)("test case %d", (index, input, expected, value, argNum) => {
|
||||
const result = enumTypeGetter(
|
||||
value as string,
|
||||
argNum as number,
|
||||
input as string,
|
||||
);
|
||||
expect(result).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
import {
|
||||
ACTION_TRIGGER_REGEX,
|
||||
FUNC_ARGS_REGEX,
|
||||
IS_URL_OR_MODAL,
|
||||
} from "./regex";
|
||||
import {
|
||||
getDynamicBindings,
|
||||
isDynamicValue,
|
||||
} from "../../../utils/DynamicBindingUtils";
|
||||
|
||||
export const stringToJS = (string: string): string => {
|
||||
const { jsSnippets, stringSegments } = getDynamicBindings(string);
|
||||
return stringSegments
|
||||
.map((segment, index) => {
|
||||
if (jsSnippets[index] && jsSnippets[index].length > 0) {
|
||||
return jsSnippets[index];
|
||||
} else {
|
||||
return `'${segment}'`;
|
||||
}
|
||||
})
|
||||
.join(" + ");
|
||||
};
|
||||
|
||||
export const JSToString = (js: string): string => {
|
||||
const segments = js.split(" + ");
|
||||
return segments
|
||||
.map((segment) => {
|
||||
if (segment.charAt(0) === "'") {
|
||||
return segment.substring(1, segment.length - 1);
|
||||
} else return "{{" + segment + "}}";
|
||||
})
|
||||
.join("");
|
||||
};
|
||||
|
||||
export const argsStringToArray = (funcArgs: string): string[] => {
|
||||
const argsplitMatches = [...funcArgs.matchAll(FUNC_ARGS_REGEX)];
|
||||
const arr: string[] = [];
|
||||
let isPrevUndefined = true;
|
||||
for (const match of argsplitMatches) {
|
||||
const matchVal = match[0];
|
||||
if (!matchVal || matchVal === "") {
|
||||
if (isPrevUndefined) {
|
||||
arr.push(matchVal);
|
||||
}
|
||||
isPrevUndefined = true;
|
||||
} else {
|
||||
isPrevUndefined = false;
|
||||
arr.push(matchVal);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
export const modalSetter = (changeValue: any, currentValue: string) => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = matches[0][2].split(",");
|
||||
if (isDynamicValue(changeValue)) {
|
||||
args[0] = `${changeValue.substring(2, changeValue.length - 2)}`;
|
||||
} else {
|
||||
args[0] = `'${changeValue}'`;
|
||||
}
|
||||
}
|
||||
return currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
};
|
||||
|
||||
export const modalGetter = (value: string) => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let name = "none";
|
||||
if (!matches.length) {
|
||||
return name;
|
||||
} else {
|
||||
const modalName = matches[0][2].split(",")[0];
|
||||
if (IS_URL_OR_MODAL.test(modalName) || modalName === "") {
|
||||
name = modalName.substring(1, modalName.length - 1);
|
||||
} else {
|
||||
name = `{{${modalName}}}`;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
export const textSetter = (
|
||||
changeValue: any,
|
||||
currentValue: string,
|
||||
argNum: number,
|
||||
): string => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = argsStringToArray(matches[0][2]);
|
||||
args[argNum] = stringToJS(changeValue);
|
||||
}
|
||||
return currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
};
|
||||
|
||||
export const textGetter = (value: string, argNum: number) => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
if (!matches.length) {
|
||||
return "";
|
||||
} else {
|
||||
const args = argsStringToArray(matches[0][2]);
|
||||
const arg = args[argNum];
|
||||
return arg ? JSToString(arg.trim()) : arg;
|
||||
}
|
||||
};
|
||||
|
||||
export const enumTypeSetter = (
|
||||
changeValue: any,
|
||||
currentValue: string,
|
||||
argNum: number,
|
||||
): string => {
|
||||
const matches = [...currentValue.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
let args: string[] = [];
|
||||
if (matches.length) {
|
||||
args = argsStringToArray(matches[0][2]);
|
||||
args[argNum] = changeValue as string;
|
||||
}
|
||||
return currentValue.replace(
|
||||
ACTION_TRIGGER_REGEX,
|
||||
`{{$1(${args.join(",")})}}`,
|
||||
);
|
||||
};
|
||||
|
||||
export const enumTypeGetter = (
|
||||
value: string,
|
||||
argNum: number,
|
||||
defaultValue = "",
|
||||
): string => {
|
||||
const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)];
|
||||
if (!matches.length) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
const args = argsStringToArray(matches[0][2]);
|
||||
const arg = args[argNum];
|
||||
return arg ? arg.trim() : defaultValue;
|
||||
}
|
||||
};
|
||||
|
|
@ -15,7 +15,7 @@ import { isString } from "utils/helpers";
|
|||
import {
|
||||
JSToString,
|
||||
stringToJS,
|
||||
} from "components/editorComponents/ActionCreator/Fields";
|
||||
} from "components/editorComponents/ActionCreator/utils";
|
||||
import CodeEditor from "components/editorComponents/LazyCodeEditorWrapper";
|
||||
|
||||
const PromptMessage = styled.span`
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { isString } from "utils/helpers";
|
|||
import {
|
||||
JSToString,
|
||||
stringToJS,
|
||||
} from "components/editorComponents/ActionCreator/Fields";
|
||||
} from "components/editorComponents/ActionCreator/utils";
|
||||
import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
|
||||
|
||||
const PromptMessage = styled.span`
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { isString } from "utils/helpers";
|
|||
import {
|
||||
JSToString,
|
||||
stringToJS,
|
||||
} from "components/editorComponents/ActionCreator/Fields";
|
||||
} from "components/editorComponents/ActionCreator/utils";
|
||||
import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
|
||||
import {
|
||||
ORIGINAL_INDEX_KEY,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user