diff --git a/app/client/src/components/editorComponents/actioncreator/ActionCreator.tsx b/app/client/src/components/editorComponents/actioncreator/ActionCreator.tsx index 5580a56df0..b4972324bd 100644 --- a/app/client/src/components/editorComponents/actioncreator/ActionCreator.tsx +++ b/app/client/src/components/editorComponents/actioncreator/ActionCreator.tsx @@ -152,9 +152,6 @@ type SelectorViewProps = ViewProps & { options: TreeDropdownOption[]; defaultText: string; getDefaults?: Function; - level: number; - levelSeparator?: string; - start: boolean; displayValue?: string; selectedLabelModifier?: ( option: TreeDropdownOption, @@ -166,16 +163,13 @@ type KeyValueViewProps = ViewProps; type TextViewProps = ViewProps & { isValid: boolean; validationMessage?: string; - level: number; - start: boolean; - levelSeparator?: string; }; const views = { [ViewTypes.SELECTOR_VIEW]: function SelectorView(props: SelectorViewProps) { return ( - + {props.label && } - ); }, [ViewTypes.KEY_VALUE_VIEW]: function KeyValueView(props: KeyValueViewProps) { return ( - + - + {props.label && } - ); }, @@ -419,9 +401,6 @@ function getOptionsWithChildren( function getFieldFromValue( value: string | undefined, - level: number, - start: boolean, - levelSeparator?: string, getParentValue?: Function, ): any[] { const fields: any[] = [ @@ -429,9 +408,6 @@ function getFieldFromValue( field: FieldType.ACTION_SELECTOR_FIELD, getParentValue, value, - level, - start, - levelSeparator, }, ]; if (!value) { @@ -450,9 +426,6 @@ function getFieldFromValue( } const successFields = getFieldFromValue( `{{${sucesssValue}}}`, - level + 1, - start, - "odd", (changeValue: string) => { const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)]; const args = [...matches[0][2].matchAll(ACTION_ANONYMOUS_FUNC_REGEX)]; @@ -469,8 +442,6 @@ function getFieldFromValue( }, ); successFields[0].label = "onSuccess"; - successFields[0].level = level + 1; - successFields[0].start = true; fields.push(successFields); let errorValue; @@ -479,9 +450,6 @@ function getFieldFromValue( } const errorFields = getFieldFromValue( `{{${errorValue}}}`, - level + 1, - start, - "even", (changeValue: string) => { const matches = [...value.matchAll(ACTION_TRIGGER_REGEX)]; const args = [...matches[0][2].matchAll(ACTION_ANONYMOUS_FUNC_REGEX)]; @@ -497,51 +465,33 @@ function getFieldFromValue( }, ); errorFields[0].label = "onError"; - errorFields[0].level = level + 1; - errorFields[0].start = false; fields.push(errorFields); } return fields; } - if (value.indexOf("navigateTo") !== -1) { fields.push({ field: FieldType.URL_FIELD, - level: level + 1, - levelSeparator, - start: true, }); } if (value.indexOf("showModal") !== -1) { fields.push({ field: FieldType.SHOW_MODAL_FIELD, - level: level + 1, - levelSeparator, - start: true, }); } if (value.indexOf("closeModal") !== -1) { fields.push({ field: FieldType.CLOSE_MODAL_FIELD, - level: level + 1, - levelSeparator, - start: true, }); } if (value.indexOf("showAlert") !== -1) { fields.push( { field: FieldType.ALERT_TEXT_FIELD, - level: level + 1, - levelSeparator, - start: true, }, { field: FieldType.ALERT_TYPE_SELECTOR_FIELD, - level: level + 1, - levelSeparator, - start: false, }, ); } @@ -556,6 +506,144 @@ function getPageDropdownOptions(state: AppState) { })); } +function renderField(props: { + onValueChange: Function; + value: string; + field: any; + label?: string; + isValid: boolean; + validationMessage?: string; + apiOptionTree: TreeDropdownOption[]; + queryOptionTree: TreeDropdownOption[]; + modalDropdownList: TreeDropdownOption[]; + pageDropdownOptions: TreeDropdownOption[]; + depth: number; + maxDepth: number; +}) { + const { field } = props; + const fieldType = field.field; + const fieldConfig = fieldConfigs[fieldType]; + const view = views[fieldConfig.view]; + let viewElement: JSX.Element | null = null; + + switch (fieldType) { + case FieldType.ACTION_SELECTOR_FIELD: + case FieldType.ON_SUCCESS_FIELD: + case FieldType.ON_ERROR_FIELD: + case FieldType.SHOW_MODAL_FIELD: + case FieldType.CLOSE_MODAL_FIELD: + case FieldType.PAGE_SELECTOR_FIELD: + case FieldType.ALERT_TYPE_SELECTOR_FIELD: + let label = ""; + let defaultText = "Select Action"; + let options = props.apiOptionTree; + let selectedLabelModifier = undefined; + let displayValue = undefined; + let getDefaults = undefined; + if (fieldType === FieldType.ACTION_SELECTOR_FIELD) { + label = props.label || ""; + displayValue = + field.value !== "{{undefined}}" && field.value !== "{{()}}" + ? field.value + : undefined; + // eslint-disable-next-line react/display-name + selectedLabelModifier = ( + option: TreeDropdownOption, + displayValue?: string, + ) => { + if ( + option.type === ActionType.api || + option.type === ActionType.query + ) { + return ; + } else if (displayValue) { + return ; + } + return {option.label}; + }; + getDefaults = (value: string) => { + return { + [ActionType.navigateTo]: `'${props.pageDropdownOptions[0].label}'`, + }[value]; + }; + } + if ( + fieldType === FieldType.SHOW_MODAL_FIELD || + fieldType === FieldType.CLOSE_MODAL_FIELD + ) { + label = "Modal Name"; + options = props.modalDropdownList; + defaultText = "Select Modal"; + } + if (fieldType === FieldType.PAGE_SELECTOR_FIELD) { + label = "Page Name"; + options = props.pageDropdownOptions; + defaultText = "Select Page"; + } + if (fieldType === FieldType.ALERT_TYPE_SELECTOR_FIELD) { + label = "type"; + options = ALERT_STYLE_OPTIONS; + defaultText = "Select type"; + } + viewElement = (view as (props: SelectorViewProps) => JSX.Element)({ + options: options, + label: label, + get: fieldConfig.getter, + set: (value: string | DropdownOption, defaultValue?: string) => { + const finalValueToSet = fieldConfig.setter( + value, + props.value, + defaultValue, + ); + props.onValueChange(finalValueToSet); + }, + value: props.value, + defaultText: defaultText, + getDefaults: getDefaults, + selectedLabelModifier: selectedLabelModifier, + displayValue: displayValue ? displayValue : "", + }); + break; + case FieldType.KEY_VALUE_FIELD: + viewElement = (view as (props: SelectorViewProps) => JSX.Element)({ + options: props.apiOptionTree, + label: "", + get: fieldConfig.getter, + set: (value: string | DropdownOption) => { + const finalValueToSet = fieldConfig.setter(value, props.value); + props.onValueChange(finalValueToSet); + }, + value: props.value, + defaultText: "Select Action", + }); + break; + case FieldType.ALERT_TEXT_FIELD: + case FieldType.URL_FIELD: + let fieldLabel = ""; + if (fieldType === FieldType.ALERT_TEXT_FIELD) { + fieldLabel = "Message"; + } else if (fieldType === FieldType.URL_FIELD) { + fieldLabel = "Page Name"; + } + viewElement = (view as (props: TextViewProps) => JSX.Element)({ + label: fieldLabel, + get: fieldConfig.getter, + set: (value: string | DropdownOption) => { + const finalValueToSet = fieldConfig.setter(value, props.value); + props.onValueChange(finalValueToSet); + }, + value: props.value, + isValid: props.isValid, + validationMessage: props.validationMessage, + }); + break; + default: + break; + } + + return
{viewElement}
; +} + function Fields(props: { onValueChange: Function; value: string; @@ -570,171 +658,99 @@ function Fields(props: { depth: number; maxDepth: number; }) { - const ui = props.fields.map((field: any, index: number) => { - if (Array.isArray(field)) { - if (props.depth > props.maxDepth) { - return null; - } - const selectorField = field[0]; - console.log("selectorField", field[0], index); - return ( - { - props.onValueChange( - selectorField.getParentValue( - value.substring(2, value.length - 2), - ), - ); - }} - /> - ); - } - const fieldType = field.field; - const fieldConfig = fieldConfigs[fieldType]; - const view = views[fieldConfig.view]; - let viewElement: JSX.Element | null = null; - - switch (fieldType) { - case FieldType.ACTION_SELECTOR_FIELD: - case FieldType.ON_SUCCESS_FIELD: - case FieldType.ON_ERROR_FIELD: - case FieldType.SHOW_MODAL_FIELD: - case FieldType.CLOSE_MODAL_FIELD: - case FieldType.PAGE_SELECTOR_FIELD: - case FieldType.ALERT_TYPE_SELECTOR_FIELD: - let label = ""; - let defaultText = "Select Action"; - let options = props.apiOptionTree; - let selectedLabelModifier = undefined; - let displayValue = undefined; - let getDefaults = undefined; - if (fieldType === FieldType.ACTION_SELECTOR_FIELD) { - label = props.label || ""; - displayValue = - field.value !== "{{undefined}}" && field.value !== "{{()}}" - ? field.value - : undefined; - // eslint-disable-next-line react/display-name - selectedLabelModifier = ( - option: TreeDropdownOption, - displayValue?: string, - ) => { - if ( - option.type === ActionType.api || - option.type === ActionType.query - ) { + const { fields, ...otherProps } = props; + if (fields[0].field === FieldType.ACTION_SELECTOR_FIELD) { + const remainingFields = fields.slice(1); + return ( + + {renderField({ + field: fields[0], + ...otherProps, + })} +
    + {remainingFields.map((field: any, index: number) => { + if (Array.isArray(field)) { + if (props.depth > props.maxDepth) { + return null; + } + const selectorField = field[0]; return ( - +
  • + { + props.onValueChange( + selectorField.getParentValue( + value.substring(2, value.length - 2), + ), + ); + }} + /> +
  • + ); + } else { + return ( +
  • + {renderField({ + field: field, + ...otherProps, + })} +
  • ); - } else if (displayValue) { - return ; } - return {option.label}; - }; - getDefaults = (value: string) => { - return { - [ActionType.navigateTo]: `'${props.pageDropdownOptions[0].label}'`, - }[value]; - }; + })} +
+
+ ); + } else { + const ui = fields.map((field: any, index: number) => { + if (Array.isArray(field)) { + if (props.depth > props.maxDepth) { + return null; } - if ( - fieldType === FieldType.SHOW_MODAL_FIELD || - fieldType === FieldType.CLOSE_MODAL_FIELD - ) { - label = "Modal Name"; - options = props.modalDropdownList; - defaultText = "Select Modal"; - } - if (fieldType === FieldType.PAGE_SELECTOR_FIELD) { - label = "Page Name"; - options = props.pageDropdownOptions; - defaultText = "Select Page"; - } - if (fieldType === FieldType.ALERT_TYPE_SELECTOR_FIELD) { - label = "type"; - options = ALERT_STYLE_OPTIONS; - defaultText = "Select type"; - } - viewElement = (view as (props: SelectorViewProps) => JSX.Element)({ - options: options, - label: label, - get: fieldConfig.getter, - set: (value: string | DropdownOption, defaultValue?: string) => { - const finalValueToSet = fieldConfig.setter( - value, - props.value, - defaultValue, - ); - props.onValueChange(finalValueToSet); - }, - value: props.value, - defaultText: defaultText, - getDefaults: getDefaults, - selectedLabelModifier: selectedLabelModifier, - displayValue: displayValue ? displayValue : "", - level: field.level, - start: field.start, - levelSeparator: field.levelSeparator, + const selectorField = field[0]; + return ( + { + props.onValueChange( + selectorField.getParentValue( + value.substring(2, value.length - 2), + ), + ); + }} + /> + ); + } else { + return renderField({ + field: field, + ...otherProps, }); - break; - case FieldType.KEY_VALUE_FIELD: - viewElement = (view as (props: SelectorViewProps) => JSX.Element)({ - options: props.apiOptionTree, - label: "", - get: fieldConfig.getter, - set: (value: string | DropdownOption) => { - const finalValueToSet = fieldConfig.setter(value, props.value); - props.onValueChange(finalValueToSet); - }, - value: props.value, - defaultText: "Select Action", - level: field.level, - start: field.start, - levelSeparator: field.levelSeparator, - }); - break; - case FieldType.ALERT_TEXT_FIELD: - case FieldType.URL_FIELD: - let fieldLabel = ""; - if (fieldType === FieldType.ALERT_TEXT_FIELD) { - fieldLabel = "Message"; - } else if (fieldType === FieldType.URL_FIELD) { - fieldLabel = "Page Name"; - } - viewElement = (view as (props: TextViewProps) => JSX.Element)({ - label: fieldLabel, - get: fieldConfig.getter, - set: (value: string | DropdownOption) => { - const finalValueToSet = fieldConfig.setter(value, props.value); - props.onValueChange(finalValueToSet); - }, - value: props.value, - isValid: props.isValid, - validationMessage: props.validationMessage, - level: field.level, - start: field.start, - levelSeparator: field.levelSeparator, - }); - break; - default: - break; - } - - return
{viewElement}
; - }); - - return <>{ui}; + } + }); + return <>{ui}; + } } function useModalDropdownList() { @@ -843,21 +859,22 @@ export function ActionCreator(props: ActionCreatorProps) { const queryOptionTree = useQueryOptionTree(); const modalDropdownList = useModalDropdownList(); const pageDropdownOptions = useSelector(getPageDropdownOptions); - const fields = getFieldFromValue(props.value, 0, false); - console.log("fields", fields); + const fields = getFieldFromValue(props.value); return ( - + + + ); } diff --git a/app/client/src/components/propertyControls/StyledControls.tsx b/app/client/src/components/propertyControls/StyledControls.tsx index e9b5e0faa8..0df23e53c3 100644 --- a/app/client/src/components/propertyControls/StyledControls.tsx +++ b/app/client/src/components/propertyControls/StyledControls.tsx @@ -17,7 +17,7 @@ import { Skin } from "constants/DefaultTheme"; type ControlWrapperProps = { orientation?: ContainerOrientation; - level?: number; + isAction?: boolean; }; export const ControlWrapper = styled.div` @@ -26,8 +26,7 @@ export const ControlWrapper = styled.div` align-items: center; flex-direction: ${props => props.orientation === "VERTICAL" ? "column" : "row"}; - padding: ${props => props.theme.spaces[3]}px 0; - padding-left: ${props => (props.level ? 18 * props.level : 0)}px; + padding: ${props => (props.isAction ? "0" : "8px 0 ")}; & > label { color: ${props => props.theme.colors.paneText}; margin-bottom: ${props => props.theme.spaces[1]}px; @@ -81,6 +80,16 @@ export const StyledDropDownContainer = styled.div` border: none; box-shadow: none; background: transparent; + white-space: normal; + word-break: break-word; + } + .bp3-button-text { + white-space: normal; + word-break: break-word; + display: block; + overflow: auto; + } + .bp3-icon { } } } diff --git a/app/client/src/components/utils/TreeStructure.tsx b/app/client/src/components/utils/TreeStructure.tsx index e875c09545..bcf2b5bede 100644 --- a/app/client/src/components/utils/TreeStructure.tsx +++ b/app/client/src/components/utils/TreeStructure.tsx @@ -1,89 +1,72 @@ import React from "react"; import styled from "styled-components"; +const TreeStructureWrapper = styled.div` + li { + list-style: none; + } + + .tree, + .tree ul { + margin-bottom: 0; + margin-top: 0; + margin-left: 9px; + padding: 0; + list-style: none; + color: ${props => props.theme.colors.paneText}; + position: relative; + } + + .tree ul { + margin-left: 9px; + } + + .tree:before, + .tree ul:before { + content: ""; + display: block; + width: 0; + position: absolute; + top: 0; + bottom: 0; + left: 0; + border-left: 2px solid; + } + + .tree li { + margin: 0; + padding-left: 9px; + line-height: 18px; + padding-top: 16px; + position: relative; + } + + .tree li:before { + content: ""; + display: block; + width: 9px; + height: 0; + border-top: 2px solid; + margin-top: 36px; + position: absolute; + top: 18px; + left: 0; + } + + .tree li:last-child:before { + background: ${props => props.theme.colors.paneBG}; + height: auto; + top: 18px; + bottom: 0; + } +`; + type TreeStructureProps = { - label: string; - level: number; - start: boolean; - levelSeparator?: string; + children: React.ReactNode; }; -const TreeStructureHorizontalWrapper = styled.div<{ - level: number; - label: string; -}>` - position: absolute; - width: ${props => (props.level - 1) * 2 + 9}px; - height: 2px; - background: #a2a6a8; - top: ${props => (props.label ? "65%" : "50%")}; - left: ${props => (props.level - 1) * 18 + 9}px; - z-index: 1; -`; - -const TreeStructureVerticalWrapper = styled.div<{ - level: number; - label: string; - start: boolean; -}>` - position: absolute; - height: ${props => (props.start ? (props.label ? "77%" : "70%") : "100%")}; - width: 2px; - background: #a2a6a8; - top: ${props => - props.start - ? props.label - ? "-12%" - : "-16%" - : props.label - ? "-35%" - : "-49%"}; - left: ${props => (props.level - 1) * 18 + 9}px; - z-index: 1; -`; - const TreeStructure = (props: TreeStructureProps) => { - return ( - - {props.level ? ( - - ) : null} - {(() => { - if ( - props.level && - props.levelSeparator && - props.levelSeparator === "odd" - ) { - const treeStructureVerticalWrappers = new Array(props.level) - .fill("") - .map((i, index) => { - return ( - - ); - }); - return treeStructureVerticalWrappers; - } else if (props.level) { - return ( - - ); - } else { - return []; - } - })()} - - ); + return {props.children}; }; export default TreeStructure;