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:
Rimil Dey 2022-09-26 10:05:04 +05:30 committed by GitHub
parent a64f27ce27
commit 4e9068ddba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 713 additions and 427 deletions

View File

@ -1244,3 +1244,11 @@ export const GENERATE_PAGE = () => "Generate page from data table";
export const GENERATE_PAGE_DESCRIPTION = () => export const GENERATE_PAGE_DESCRIPTION = () =>
"Start app with a simple CRUD UI and customize it"; "Start app with a simple CRUD UI and customize it";
export const ADD_PAGE_FROM_TEMPLATE = () => "Add Page From Template"; 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" },
];

View File

@ -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);
},
);
});

View File

@ -1,11 +1,9 @@
import React from "react"; import React from "react";
import { import {
TreeDropdown, TreeDropdown,
Setter, Setter,
TreeDropdownOption, TreeDropdownOption,
Switcher, Switcher,
SwitcherProps,
} from "design-system"; } from "design-system";
import { import {
ControlWrapper, ControlWrapper,
@ -16,7 +14,6 @@ import {
} from "components/propertyControls/StyledControls"; } from "components/propertyControls/StyledControls";
import { KeyValueComponent } from "components/propertyControls/KeyValueComponent"; import { KeyValueComponent } from "components/propertyControls/KeyValueComponent";
import { InputText } from "components/propertyControls/InputTextControl"; import { InputText } from "components/propertyControls/InputTextControl";
import { getDynamicBindings, isDynamicValue } from "utils/DynamicBindingUtils";
import HightlightedCode from "components/editorComponents/HighlightedCode"; import HightlightedCode from "components/editorComponents/HighlightedCode";
import { Skin } from "constants/DefaultTheme"; import { Skin } from "constants/DefaultTheme";
import { DropdownOption } from "components/constants"; import { DropdownOption } from "components/constants";
@ -26,13 +23,33 @@ import DividerComponent from "widgets/DividerWidget/component";
import store from "store"; import store from "store";
import { getPageList } from "selectors/entitiesSelector"; import { getPageList } from "selectors/entitiesSelector";
import { import {
APPSMITH_GLOBAL_FUNCTIONS, RESET_CHILDREN_OPTIONS,
APPSMITH_NAMESPACED_FUNCTIONS, FILE_TYPE_OPTIONS,
NAVIGATION_TARGET_FIELD_OPTIONS,
ViewTypes,
AppsmithFunction,
FieldType,
} from "./constants"; } from "./constants";
import { PopoverPosition } from "@blueprintjs/core"; import { PopoverPosition } from "@blueprintjs/core";
import { ACTION_TRIGGER_REGEX } from "./regex";
/* eslint-disable @typescript-eslint/ban-types */ import {
/* TODO: Function and object types need to be updated to enable the lint rule */ 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 ******* ******** 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 * 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 = { const views = {
[ViewTypes.SELECTOR_VIEW]: function SelectorView(props: SelectorViewProps) { [ViewTypes.SELECTOR_VIEW]: function SelectorView(props: SelectorViewProps) {
return ( 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 = { const fieldConfigs: FieldConfigs = {
[FieldType.ACTION_SELECTOR_FIELD]: { [FieldType.ACTION_SELECTOR_FIELD]: {
getter: (storedValue: string) => { getter: (storedValue: string) => {
@ -406,9 +155,9 @@ const fieldConfigs: FieldConfigs = {
? [...storedValue.matchAll(ACTION_TRIGGER_REGEX)] ? [...storedValue.matchAll(ACTION_TRIGGER_REGEX)]
: []; : [];
} }
let mainFuncSelectedValue = ActionType.none; let mainFuncSelectedValue = AppsmithFunction.none;
if (matches.length) { if (matches.length) {
mainFuncSelectedValue = matches[0][1] || ActionType.none; mainFuncSelectedValue = matches[0][1] || AppsmithFunction.none;
} }
const mainFuncSelectedValueSplit = mainFuncSelectedValue.split("."); const mainFuncSelectedValueSplit = mainFuncSelectedValue.split(".");
if (mainFuncSelectedValueSplit[1] === "run") { if (mainFuncSelectedValueSplit[1] === "run") {
@ -422,22 +171,22 @@ const fieldConfigs: FieldConfigs = {
let defaultParams = ""; let defaultParams = "";
let defaultArgs: Array<any> = []; let defaultArgs: Array<any> = [];
switch (type) { switch (type) {
case ActionType.integration: case AppsmithFunction.integration:
value = `${value}.run`; value = `${value}.run`;
break; break;
case ActionType.navigateTo: case AppsmithFunction.navigateTo:
defaultParams = `'', {}, 'SAME_WINDOW'`; defaultParams = `'', {}, 'SAME_WINDOW'`;
break; break;
case ActionType.jsFunction: case AppsmithFunction.jsFunction:
defaultArgs = option.args ? option.args : []; defaultArgs = option.args ? option.args : [];
break; break;
case ActionType.setInterval: case AppsmithFunction.setInterval:
defaultParams = "() => { \n\t // add code here \n}, 5000"; defaultParams = "() => { \n\t // add code here \n}, 5000";
break; break;
case ActionType.getGeolocation: case AppsmithFunction.getGeolocation:
defaultParams = "(location) => { \n\t // add code here \n }"; defaultParams = "(location) => { \n\t // add code here \n }";
break; break;
case ActionType.resetWidget: case AppsmithFunction.resetWidget:
defaultParams = `"",true`; defaultParams = `"",true`;
break; break;
default: default:
@ -687,7 +436,7 @@ const fieldConfigs: FieldConfigs = {
}; };
function renderField(props: { function renderField(props: {
onValueChange: Function; onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
value: string; value: string;
field: { field: FieldType; value: string; label: string; index: number }; field: { field: FieldType; value: string; label: string; index: number };
label?: string; label?: string;
@ -698,8 +447,8 @@ function renderField(props: {
depth: number; depth: number;
maxDepth: number; maxDepth: number;
additionalAutoComplete?: Record<string, Record<string, unknown>>; additionalAutoComplete?: Record<string, Record<string, unknown>>;
activeNavigateToTab: Switch; activeNavigateToTab: SwitchType;
navigateToSwitches: Array<Switch>; navigateToSwitches: Array<SwitchType>;
}) { }) {
const { field } = props; const { field } = props;
const fieldType = field.field; const fieldType = field.field;
@ -739,7 +488,7 @@ function renderField(props: {
option: TreeDropdownOption, option: TreeDropdownOption,
displayValue?: string, displayValue?: string,
) { ) {
if (option.type === ActionType.integration) { if (option.type === AppsmithFunction.integration) {
return ( return (
<HightlightedCode <HightlightedCode
codeText={`{{${option.label}.run()}}`} codeText={`{{${option.label}.run()}}`}
@ -755,7 +504,7 @@ function renderField(props: {
}; };
getDefaults = (value: string) => { getDefaults = (value: string) => {
return { return {
[ActionType.navigateTo]: `'${props.pageDropdownOptions[0].label}'`, [AppsmithFunction.navigateTo]: `'${props.pageDropdownOptions[0].label}'`,
}[value]; }[value];
}; };
} }
@ -838,7 +587,7 @@ function renderField(props: {
props.value, props.value,
props.field.index, props.field.index,
); );
props.onValueChange(finalValueToSet); props.onValueChange(finalValueToSet, false);
}, },
index: props.field.index, index: props.field.index,
value: props.value || "", value: props.value || "",
@ -851,7 +600,7 @@ function renderField(props: {
get: fieldConfig.getter, get: fieldConfig.getter,
set: (value: string | DropdownOption) => { set: (value: string | DropdownOption) => {
const finalValueToSet = fieldConfig.setter(value, props.value); const finalValueToSet = fieldConfig.setter(value, props.value);
props.onValueChange(finalValueToSet); props.onValueChange(finalValueToSet, false);
}, },
value: props.value, value: props.value,
defaultText: "Select Action", defaultText: "Select Action",
@ -918,7 +667,7 @@ function renderField(props: {
} }
function Fields(props: { function Fields(props: {
onValueChange: Function; onValueChange: (newValue: string, isUpdatedViaKeyboard: boolean) => void;
value: string; value: string;
fields: any; fields: any;
label?: string; label?: string;
@ -929,8 +678,8 @@ function Fields(props: {
depth: number; depth: number;
maxDepth: number; maxDepth: number;
additionalAutoComplete?: Record<string, Record<string, unknown>>; additionalAutoComplete?: Record<string, Record<string, unknown>>;
navigateToSwitches: Array<Switch>; navigateToSwitches: Array<SwitchType>;
activeNavigateToTab: Switch; activeNavigateToTab: SwitchType;
}) { }) {
const { fields, ...otherProps } = props; const { fields, ...otherProps } = props;

View File

@ -16,3 +16,85 @@ export const APPSMITH_NAMESPACED_FUNCTIONS = {
watchGeolocation: "appsmith.geolocation.watchPosition", watchGeolocation: "appsmith.geolocation.watchPosition",
stopWatchGeolocation: "appsmith.geolocation.clearWatch", 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",
}

View File

@ -24,12 +24,7 @@ import {
getModalDropdownList, getModalDropdownList,
getNextModalName, getNextModalName,
} from "selectors/widgetSelectors"; } from "selectors/widgetSelectors";
import Fields, { import Fields from "./Fields";
ACTION_ANONYMOUS_FUNC_REGEX,
ACTION_TRIGGER_REGEX,
ActionType,
FieldType,
} from "./Fields";
import { getDataTree } from "selectors/dataTreeSelectors"; import { getDataTree } from "selectors/dataTreeSelectors";
import { DataTree, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory"; import { DataTree, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
import { getEntityNameAndPropertyPath } from "workers/evaluationUtils"; import { getEntityNameAndPropertyPath } from "workers/evaluationUtils";
@ -62,69 +57,74 @@ import { selectFeatureFlags } from "selectors/usersSelectors";
import FeatureFlags from "entities/FeatureFlags"; import FeatureFlags from "entities/FeatureFlags";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { isValidURL } from "utils/URLUtils"; 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 }[] = [ const baseOptions: { label: string; value: string }[] = [
{ {
label: createMessage(NO_ACTION), label: createMessage(NO_ACTION),
value: ActionType.none, value: AppsmithFunction.none,
}, },
{ {
label: createMessage(EXECUTE_A_QUERY), label: createMessage(EXECUTE_A_QUERY),
value: ActionType.integration, value: AppsmithFunction.integration,
}, },
{ {
label: createMessage(NAVIGATE_TO), label: createMessage(NAVIGATE_TO),
value: ActionType.navigateTo, value: AppsmithFunction.navigateTo,
}, },
{ {
label: createMessage(SHOW_MESSAGE), label: createMessage(SHOW_MESSAGE),
value: ActionType.showAlert, value: AppsmithFunction.showAlert,
}, },
{ {
label: createMessage(OPEN_MODAL), label: createMessage(OPEN_MODAL),
value: ActionType.showModal, value: AppsmithFunction.showModal,
}, },
{ {
label: createMessage(CLOSE_MODAL), label: createMessage(CLOSE_MODAL),
value: ActionType.closeModal, value: AppsmithFunction.closeModal,
}, },
{ {
label: createMessage(STORE_VALUE), label: createMessage(STORE_VALUE),
value: ActionType.storeValue, value: AppsmithFunction.storeValue,
}, },
{ {
label: createMessage(DOWNLOAD), label: createMessage(DOWNLOAD),
value: ActionType.download, value: AppsmithFunction.download,
}, },
{ {
label: createMessage(COPY_TO_CLIPBOARD), label: createMessage(COPY_TO_CLIPBOARD),
value: ActionType.copyToClipboard, value: AppsmithFunction.copyToClipboard,
}, },
{ {
label: createMessage(RESET_WIDGET), label: createMessage(RESET_WIDGET),
value: ActionType.resetWidget, value: AppsmithFunction.resetWidget,
}, },
{ {
label: createMessage(SET_INTERVAL), label: createMessage(SET_INTERVAL),
value: ActionType.setInterval, value: AppsmithFunction.setInterval,
}, },
{ {
label: createMessage(CLEAR_INTERVAL), label: createMessage(CLEAR_INTERVAL),
value: ActionType.clearInterval, value: AppsmithFunction.clearInterval,
}, },
{ {
label: createMessage(GET_GEO_LOCATION), label: createMessage(GET_GEO_LOCATION),
value: ActionType.getGeolocation, value: AppsmithFunction.getGeolocation,
}, },
{ {
label: createMessage(WATCH_GEO_LOCATION), label: createMessage(WATCH_GEO_LOCATION),
value: ActionType.watchGeolocation, value: AppsmithFunction.watchGeolocation,
}, },
{ {
label: createMessage(STOP_WATCH_GEO_LOCATION), 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; const { JS_EDITOR: isJSEditorEnabled } = featureFlags;
if (isJSEditorEnabled) { if (isJSEditorEnabled) {
const jsOption = baseOptions.find( const jsOption = baseOptions.find(
(option: any) => option.value === ActionType.jsFunction, (option: any) => option.value === AppsmithFunction.jsFunction,
); );
if (!jsOption) { if (!jsOption) {
baseOptions.splice(2, 0, { baseOptions.splice(2, 0, {
label: createMessage(EXECUTE_JS_FUNCTION), label: createMessage(EXECUTE_JS_FUNCTION),
value: ActionType.jsFunction, value: AppsmithFunction.jsFunction,
}); });
} }
} }
return baseOptions; return baseOptions;
}; };
type Switch = {
id: string;
text: string;
action: () => void;
};
function getFieldFromValue( function getFieldFromValue(
value: string | undefined, value: string | undefined,
activeTabNavigateTo: Switch, activeTabNavigateTo: SwitchType,
getParentValue?: Function, getParentValue?: (changeValue: string) => string,
dataTree?: DataTree, dataTree?: DataTree,
): any[] { ): any[] {
const fields: any[] = []; const fields: any[] = [];
@ -408,7 +402,7 @@ function useModalDropdownList() {
id: "create", id: "create",
icon: "plus", icon: "plus",
className: "t--create-modal-btn", className: "t--create-modal-btn",
onSelect: (option: TreeDropdownOption, setter?: Function) => { onSelect: (option: TreeDropdownOption, setter?: GenericFunction) => {
const modalName = nextModalName; const modalName = nextModalName;
if (setter) { if (setter) {
setter({ setter({
@ -459,11 +453,11 @@ function getIntegrationOptionsWithChildren(
action.config.pluginType === PluginType.REMOTE, action.config.pluginType === PluginType.REMOTE,
); );
const option = options.find( const option = options.find(
(option) => option.value === ActionType.integration, (option) => option.value === AppsmithFunction.integration,
); );
const jsOption = options.find( const jsOption = options.find(
(option) => option.value === ActionType.jsFunction, (option) => option.value === AppsmithFunction.jsFunction,
); );
if (option) { 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) => { const isValueValidURL = (value: string) => {
if (value) { if (value) {
const indices = []; const indices = [];
@ -613,7 +595,7 @@ const isValueValidURL = (value: string) => {
const ActionCreator = React.forwardRef( const ActionCreator = React.forwardRef(
(props: ActionCreatorProps, ref: any) => { (props: ActionCreatorProps, ref: any) => {
const NAVIGATE_TO_TAB_SWITCHER: Array<Switch> = [ const NAVIGATE_TO_TAB_SWITCHER: Array<SwitchType> = [
{ {
id: "page-name", id: "page-name",
text: "Page Name", text: "Page Name",

View File

@ -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 = /^'.*'$/;

View File

@ -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[];
};

View File

@ -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);
});
});

View File

@ -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;
}
};

View File

@ -15,7 +15,7 @@ import { isString } from "utils/helpers";
import { import {
JSToString, JSToString,
stringToJS, stringToJS,
} from "components/editorComponents/ActionCreator/Fields"; } from "components/editorComponents/ActionCreator/utils";
import CodeEditor from "components/editorComponents/LazyCodeEditorWrapper"; import CodeEditor from "components/editorComponents/LazyCodeEditorWrapper";
const PromptMessage = styled.span` const PromptMessage = styled.span`

View File

@ -17,7 +17,7 @@ import { isString } from "utils/helpers";
import { import {
JSToString, JSToString,
stringToJS, stringToJS,
} from "components/editorComponents/ActionCreator/Fields"; } from "components/editorComponents/ActionCreator/utils";
import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator"; import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
const PromptMessage = styled.span` const PromptMessage = styled.span`

View File

@ -17,7 +17,7 @@ import { isString } from "utils/helpers";
import { import {
JSToString, JSToString,
stringToJS, stringToJS,
} from "components/editorComponents/ActionCreator/Fields"; } from "components/editorComponents/ActionCreator/utils";
import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator"; import { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
import { import {
ORIGINAL_INDEX_KEY, ORIGINAL_INDEX_KEY,