Feature/option to upload file or text in multipart form (#6534)
* added option to multipart form data for file or text upload * updated styles for the dynamic-text-field-with-dropdown styled component * added cypress tests for multipart body type * code refactor: moved constants to ApiEditorConstants.ts * updated multipart dropdown styles * minor bug fix
This commit is contained in:
parent
30c11e4a74
commit
f0c7ce0e89
|
|
@ -43,6 +43,7 @@
|
|||
"next": "?page=2&pageSize=10",
|
||||
"prev": "?page=1&pageSize=10",
|
||||
"apiFormDataBodyType": "x-www-form-urlencoded",
|
||||
"apiMultipartBodyType": "multi-part",
|
||||
"defaultMoustacheData": "{{Input1.text",
|
||||
"defaultInputWidget": "{{Table1.selectedRow.id",
|
||||
"deafultDropDownWidget": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
const testdata = require("../../../../fixtures/testdata.json");
|
||||
const apiEditor = require("../../../../locators/ApiEditor.json");
|
||||
const apiwidget = require("../../../../locators/apiWidgetslocator.json");
|
||||
|
||||
describe("API Panel request body", function() {
|
||||
it("Check whether input and type dropdown selector exist when multi-part is selected", function() {
|
||||
cy.NavigateToAPI_Panel();
|
||||
cy.CreateAPI("FirstAPI");
|
||||
|
||||
cy.SelectAction(testdata.postAction);
|
||||
|
||||
cy.contains(apiEditor.bodyTab).click();
|
||||
cy.contains(testdata.apiFormDataBodyType).click();
|
||||
cy.contains(testdata.apiMultipartBodyType).click();
|
||||
|
||||
cy.get(apiwidget.formEncoded).should("be.visible");
|
||||
cy.get(apiwidget.multipartTypeDropdown).should("be.visible");
|
||||
cy.DeleteAPI();
|
||||
});
|
||||
});
|
||||
|
|
@ -55,5 +55,6 @@
|
|||
"renameEntity": ".single-select >div:contains('Edit Name')",
|
||||
"paramsTab": "//li//span[text()='Params']",
|
||||
"paramKey": ".t--actionConfiguration\\.queryParameters\\[0\\]\\.key\\.0",
|
||||
"paramValue": ".t--actionConfiguration\\.queryParameters\\[0\\]\\.value\\.0"
|
||||
"paramValue": ".t--actionConfiguration\\.queryParameters\\[0\\]\\.value\\.0",
|
||||
"multipartTypeDropdown":"button:contains('Text')"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,25 @@ import { Toaster } from "components/ads/Toast";
|
|||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
|
||||
const getButtonColorStyles = (props: { theme: Theme } & ButtonStyleProps) => {
|
||||
if (props.filled) return props.theme.colors.textOnDarkBG;
|
||||
if (props.filled) {
|
||||
return props.accent === "grey"
|
||||
? props.theme.colors.textOnGreyBG
|
||||
: props.theme.colors.textOnDarkBG;
|
||||
}
|
||||
if (props.accent) {
|
||||
if (props.accent === "secondary") {
|
||||
return props.theme.colors[AccentColorMap["primary"]];
|
||||
}
|
||||
return props.theme.colors[AccentColorMap[props.accent]];
|
||||
}
|
||||
};
|
||||
|
||||
const getButtonFillStyles = (props: { theme: Theme } & ButtonStyleProps) => {
|
||||
if (props.filled) {
|
||||
return props.accent === "grey"
|
||||
? props.theme.colors.dropdownIconDarkBg
|
||||
: props.theme.colors.textOnDarkBG;
|
||||
}
|
||||
if (props.accent) {
|
||||
if (props.accent === "secondary") {
|
||||
return props.theme.colors[AccentColorMap["primary"]];
|
||||
|
|
@ -33,7 +51,7 @@ const getButtonColorStyles = (props: { theme: Theme } & ButtonStyleProps) => {
|
|||
const ButtonColorStyles = css<ButtonStyleProps>`
|
||||
color: ${getButtonColorStyles};
|
||||
svg {
|
||||
fill: ${getButtonColorStyles};
|
||||
fill: ${getButtonFillStyles};
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
@ -48,6 +66,7 @@ const AccentColorMap: Record<ButtonStyleName, string> = {
|
|||
primary: "primaryOld",
|
||||
secondary: "secondaryOld",
|
||||
error: "error",
|
||||
grey: "dropdownGreyBg",
|
||||
};
|
||||
|
||||
const ButtonWrapper = styled((props: ButtonStyleProps & IButtonProps) => (
|
||||
|
|
@ -67,9 +86,14 @@ const ButtonWrapper = styled((props: ButtonStyleProps & IButtonProps) => (
|
|||
props.accent
|
||||
? props.theme.colors[AccentColorMap[props.accent]]
|
||||
: props.theme.colors.primary};
|
||||
color: ${(props) =>
|
||||
props.accent === "grey"
|
||||
? props.theme.colors.textOnGreyBG
|
||||
: props.theme.colors.textOnDarkBG};
|
||||
border-radius: 0;
|
||||
font-weight: ${(props) => props.theme.fontWeights[2]};
|
||||
outline: none;
|
||||
|
||||
&.bp3-button {
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
|
@ -80,10 +104,10 @@ const ButtonWrapper = styled((props: ButtonStyleProps & IButtonProps) => (
|
|||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&&:hover,
|
||||
&&:focus {
|
||||
${ButtonColorStyles};
|
||||
|
|
@ -122,7 +146,7 @@ const ButtonWrapper = styled((props: ButtonStyleProps & IButtonProps) => (
|
|||
}
|
||||
`;
|
||||
|
||||
export type ButtonStyleName = "primary" | "secondary" | "error";
|
||||
export type ButtonStyleName = "primary" | "secondary" | "error" | "grey";
|
||||
|
||||
type ButtonStyleProps = {
|
||||
accent?: ButtonStyleName;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
import React, { Component, ReactNode } from "react";
|
||||
import styled from "styled-components";
|
||||
import { MenuItem, Menu, ControlGroup, InputGroup } from "@blueprintjs/core";
|
||||
import { BaseButton } from "components/designSystems/blueprint/ButtonComponent";
|
||||
import {
|
||||
MenuItem,
|
||||
Menu,
|
||||
ControlGroup,
|
||||
InputGroup,
|
||||
IMenuProps,
|
||||
} from "@blueprintjs/core";
|
||||
import {
|
||||
BaseButton,
|
||||
ButtonStyleName,
|
||||
} from "components/designSystems/blueprint/ButtonComponent";
|
||||
import {
|
||||
ItemRenderer,
|
||||
Select,
|
||||
|
|
@ -9,11 +18,40 @@ import {
|
|||
IItemListRendererProps,
|
||||
} from "@blueprintjs/select";
|
||||
import { DropdownOption } from "widgets/DropdownWidget";
|
||||
import { WrappedFieldInputProps } from "redux-form";
|
||||
|
||||
interface ButtonWrapperProps {
|
||||
width?: string;
|
||||
}
|
||||
interface MenuProps {
|
||||
width?: string;
|
||||
}
|
||||
|
||||
type MenuComponentProps = IMenuProps & MenuProps;
|
||||
|
||||
const Dropdown = Select.ofType<DropdownOption>();
|
||||
const StyledDropdown = styled(Dropdown)``;
|
||||
|
||||
const StyledButtonWrapper = styled.div<ButtonWrapperProps>`
|
||||
width: ${(props) => props.width || "100%"};
|
||||
`;
|
||||
const StyledMenu = styled(Menu)<MenuComponentProps>`
|
||||
min-width: ${(props) => props.width || "100%"};
|
||||
border-radius: 0;
|
||||
`;
|
||||
const StyledMenuItem = styled(MenuItem)`
|
||||
border-radius: 0;
|
||||
|
||||
&&&.bp3-active {
|
||||
background: ${(props) => props.theme.colors.propertyPane.activeButtonText};
|
||||
}
|
||||
`;
|
||||
|
||||
class DropdownComponent extends Component<DropdownComponentProps> {
|
||||
componentDidMount() {
|
||||
const { input, selected } = this.props;
|
||||
input && input.onChange(selected?.value);
|
||||
}
|
||||
private newItemTextInput: HTMLInputElement | null = null;
|
||||
private setNewItemTextInput = (element: HTMLInputElement | null) => {
|
||||
this.newItemTextInput = element;
|
||||
|
|
@ -41,36 +79,35 @@ class DropdownComponent extends Component<DropdownComponentProps> {
|
|||
renderItemList: ItemListRenderer<DropdownOption> = (
|
||||
props: IItemListRendererProps<DropdownOption>,
|
||||
) => {
|
||||
if (this.props.addItem) {
|
||||
const renderItems = props.items.map(props.renderItem).filter(Boolean);
|
||||
const displayMode = (
|
||||
<BaseButton
|
||||
accent="primary"
|
||||
filled
|
||||
icon-right="plus"
|
||||
onClick={this.showTextBox}
|
||||
text={this.props.addItem.displayText}
|
||||
/>
|
||||
);
|
||||
const editMode = (
|
||||
<ControlGroup fill>
|
||||
<InputGroup inputRef={this.setNewItemTextInput} />
|
||||
<BaseButton
|
||||
filled
|
||||
onClick={this.handleAddItem}
|
||||
text={this.props.addItem.displayText}
|
||||
/>
|
||||
</ControlGroup>
|
||||
);
|
||||
return (
|
||||
<Menu ulRef={props.itemsParentRef}>
|
||||
{renderItems}
|
||||
{!this.state.isEditing ? displayMode : editMode}
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
const { items, renderItem } = props;
|
||||
const { addItem, width } = this.props;
|
||||
const renderItems = items.map(renderItem).filter(Boolean);
|
||||
|
||||
return null;
|
||||
const displayMode = (
|
||||
<BaseButton
|
||||
accent="primary"
|
||||
filled
|
||||
icon-right="plus"
|
||||
onClick={this.showTextBox}
|
||||
text={addItem?.displayText}
|
||||
/>
|
||||
);
|
||||
const editMode = (
|
||||
<ControlGroup fill>
|
||||
<InputGroup inputRef={this.setNewItemTextInput} />
|
||||
<BaseButton
|
||||
filled
|
||||
onClick={this.handleAddItem}
|
||||
text={addItem?.displayText}
|
||||
/>
|
||||
</ControlGroup>
|
||||
);
|
||||
return (
|
||||
<StyledMenu ulRef={props.itemsParentRef} width={width}>
|
||||
{renderItems}
|
||||
{addItem && (!this.state.isEditing ? displayMode : editMode)}
|
||||
</StyledMenu>
|
||||
);
|
||||
};
|
||||
|
||||
searchItem = (query: string, option: DropdownOption): boolean => {
|
||||
|
|
@ -82,6 +119,7 @@ class DropdownComponent extends Component<DropdownComponentProps> {
|
|||
);
|
||||
};
|
||||
onItemSelect = (item: DropdownOption): void => {
|
||||
this.props.input?.onChange(item.value);
|
||||
this.props.selectHandler(item.value);
|
||||
};
|
||||
|
||||
|
|
@ -93,13 +131,13 @@ class DropdownComponent extends Component<DropdownComponentProps> {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<MenuItem
|
||||
<StyledMenuItem
|
||||
active={modifiers.active}
|
||||
key={option.value}
|
||||
label={option.label ? option.label : ""}
|
||||
label={this.props.hasLabel ? option.label : ""}
|
||||
onClick={handleClick}
|
||||
shouldDismissPopover={false}
|
||||
text={option.label || option.label}
|
||||
text={option.label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
@ -110,31 +148,45 @@ class DropdownComponent extends Component<DropdownComponentProps> {
|
|||
(option) => option.value === selectedValue,
|
||||
);
|
||||
|
||||
return item && (item.label || item.label);
|
||||
return item && item.label;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
accent,
|
||||
autocomplete,
|
||||
filled,
|
||||
input,
|
||||
options,
|
||||
selected,
|
||||
width,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<StyledDropdown
|
||||
activeItem={this.props.selected}
|
||||
filterable={!!this.props.autocomplete}
|
||||
itemListRenderer={this.props.addItem && this.renderItemList}
|
||||
activeItem={selected}
|
||||
filterable={!!autocomplete}
|
||||
itemListRenderer={this.renderItemList}
|
||||
itemPredicate={this.searchItem}
|
||||
itemRenderer={this.renderItem}
|
||||
items={this.props.options}
|
||||
items={options}
|
||||
itemsEqual="value"
|
||||
noResults={<MenuItem disabled text="No results." />}
|
||||
onItemSelect={this.onItemSelect}
|
||||
popoverProps={{ minimal: true }}
|
||||
{...input}
|
||||
>
|
||||
{this.props.toggle || (
|
||||
<BaseButton
|
||||
accent="secondary"
|
||||
rightIcon="chevron-down"
|
||||
text={this.getSelectedDisplayText()}
|
||||
/>
|
||||
<StyledButtonWrapper width={width}>
|
||||
<BaseButton
|
||||
accent={accent || "secondary"}
|
||||
filled={!!filled}
|
||||
rightIcon="chevron-down"
|
||||
text={this.getSelectedDisplayText()}
|
||||
/>
|
||||
</StyledButtonWrapper>
|
||||
)}
|
||||
</StyledDropdown>
|
||||
);
|
||||
|
|
@ -142,6 +194,7 @@ class DropdownComponent extends Component<DropdownComponentProps> {
|
|||
}
|
||||
|
||||
export interface DropdownComponentProps {
|
||||
hasLabel?: boolean;
|
||||
options: DropdownOption[];
|
||||
selectHandler: (selectedValue: string) => void;
|
||||
selected?: DropdownOption;
|
||||
|
|
@ -154,6 +207,10 @@ export interface DropdownComponentProps {
|
|||
addItemHandler: (name: string) => void;
|
||||
};
|
||||
toggle?: ReactNode;
|
||||
accent?: ButtonStyleName;
|
||||
filled?: boolean;
|
||||
input?: WrappedFieldInputProps;
|
||||
width?: string;
|
||||
}
|
||||
|
||||
export default DropdownComponent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
import React from "react";
|
||||
import { Field, BaseFieldProps } from "redux-form";
|
||||
import DropdownComponent from "components/editorComponents/DropdownComponent";
|
||||
import { ButtonStyleName } from "components/designSystems/blueprint/ButtonComponent";
|
||||
import { DropdownOption } from "widgets/DropdownWidget";
|
||||
|
||||
interface DynamicDropdownFieldOptions {
|
||||
options: DropdownOption[];
|
||||
accent?: ButtonStyleName;
|
||||
filled?: boolean;
|
||||
width?: string;
|
||||
}
|
||||
|
||||
type DynamicDropdownFieldProps = BaseFieldProps & DynamicDropdownFieldOptions;
|
||||
|
||||
class DynamicDropdownField extends React.Component<
|
||||
DynamicDropdownFieldProps,
|
||||
{
|
||||
selectedOption: DropdownOption;
|
||||
}
|
||||
> {
|
||||
constructor(props: DynamicDropdownFieldProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedOption: this.props.options[0],
|
||||
};
|
||||
}
|
||||
|
||||
handleOptionSelection = (selectedValue: string): void => {
|
||||
const selectedOption = this.props.options.find(
|
||||
(option) => option.value === selectedValue,
|
||||
) as DropdownOption;
|
||||
this.setState({
|
||||
selectedOption,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const dropdownProps = {
|
||||
selectHandler: this.handleOptionSelection,
|
||||
selected: this.state.selectedOption,
|
||||
};
|
||||
|
||||
return (
|
||||
<Field component={DropdownComponent} {...this.props} {...dropdownProps} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DynamicDropdownField;
|
||||
|
|
@ -30,6 +30,7 @@ class DynamicTextField extends React.Component<
|
|||
theme: this.props.theme || EditorTheme.LIGHT,
|
||||
size: this.props.size || EditorSize.COMPACT,
|
||||
};
|
||||
|
||||
return <Field component={CodeEditor} {...this.props} {...editorProps} />;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@ import {
|
|||
import Text, { Case, TextType } from "components/ads/Text";
|
||||
import { Classes } from "components/ads/common";
|
||||
import { AutocompleteDataType } from "utils/autocomplete/TernServer";
|
||||
import DynamicDropdownField from "./DynamicDropdownField";
|
||||
import { Colors } from "constants/Colors";
|
||||
import {
|
||||
DEFAULT_MULTI_PART_DROPDOWN_WIDTH,
|
||||
MULTI_PART_DROPDOWN_OPTIONS,
|
||||
} from "constants/ApiEditorConstants";
|
||||
|
||||
type CustomStack = {
|
||||
removeTopPadding?: boolean;
|
||||
|
|
@ -83,6 +89,23 @@ const FlexContainer = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
const DynamicTextFieldWithDropdownWrapper = styled.div`
|
||||
display: flex;
|
||||
position: relative;
|
||||
border-bottom: solid 1px ${Colors.MERCURY};
|
||||
margin-bottom: 10px;
|
||||
top: -2px;
|
||||
& .CodeEditorTarget * {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const DynamicDropdownFieldWrapper = styled.div`
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-left: 5px;
|
||||
`;
|
||||
|
||||
const expected = {
|
||||
type: FIELD_VALUES.API_ACTION.params,
|
||||
example: "",
|
||||
|
|
@ -136,16 +159,41 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
return (
|
||||
<FormRowWithLabel key={index}>
|
||||
<Flex size={1}>
|
||||
<DynamicTextField
|
||||
border={CodeEditorBorder.BOTTOM_SIDE}
|
||||
className={`t--${field}.key.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].key`}
|
||||
expected={expected}
|
||||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
theme={props.theme}
|
||||
/>
|
||||
{props.hasType ? (
|
||||
<DynamicTextFieldWithDropdownWrapper>
|
||||
<DynamicTextField
|
||||
border={CodeEditorBorder.BOTTOM_SIDE}
|
||||
className={`t--${field}.key.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].key`}
|
||||
expected={expected}
|
||||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
theme={props.theme}
|
||||
/>
|
||||
|
||||
<DynamicDropdownFieldWrapper>
|
||||
<DynamicDropdownField
|
||||
accent="grey"
|
||||
filled
|
||||
name={`${field}.type`}
|
||||
options={MULTI_PART_DROPDOWN_OPTIONS}
|
||||
width={DEFAULT_MULTI_PART_DROPDOWN_WIDTH}
|
||||
/>
|
||||
</DynamicDropdownFieldWrapper>
|
||||
</DynamicTextFieldWithDropdownWrapper>
|
||||
) : (
|
||||
<DynamicTextField
|
||||
border={CodeEditorBorder.BOTTOM_SIDE}
|
||||
className={`t--${field}.key.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].key`}
|
||||
expected={expected}
|
||||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
theme={props.theme}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{!props.actionConfig && (
|
||||
|
|
@ -239,6 +287,7 @@ type Props = {
|
|||
dataTreePath?: string;
|
||||
hideHeader?: boolean;
|
||||
theme?: EditorTheme;
|
||||
hasType?: boolean;
|
||||
};
|
||||
|
||||
function KeyValueFieldArray(props: Props) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export const CONTENT_TYPE_HEADER_KEY = "content-type";
|
|||
export enum ApiContentTypes {
|
||||
JSON = "json",
|
||||
FORM_URLENCODED = "x-www-form-urlencoded",
|
||||
MULTIPART_FORM_DATA = "form-data",
|
||||
MULTIPART_FORM_DATA = "multi-part",
|
||||
RAW = "raw",
|
||||
}
|
||||
|
||||
|
|
@ -74,3 +74,26 @@ export const POST_BODY_FORMAT_TITLES = POST_BODY_FORMAT_OPTIONS.map(
|
|||
return { title: option.label, key: option.value };
|
||||
},
|
||||
);
|
||||
|
||||
export enum MultiPartOptionTypes {
|
||||
TEXT = "Text",
|
||||
FILE = "File",
|
||||
}
|
||||
|
||||
export interface MULTI_PART_DROPDOWN_OPTION {
|
||||
label: MultiPartOptionTypes;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const MULTI_PART_DROPDOWN_OPTIONS: MULTI_PART_DROPDOWN_OPTION[] = [
|
||||
{
|
||||
label: MultiPartOptionTypes.TEXT,
|
||||
value: "TEXT",
|
||||
},
|
||||
{
|
||||
label: MultiPartOptionTypes.FILE,
|
||||
value: "FILE",
|
||||
},
|
||||
];
|
||||
|
||||
export const DEFAULT_MULTI_PART_DROPDOWN_WIDTH = "75px";
|
||||
|
|
|
|||
|
|
@ -2706,6 +2706,7 @@ export const theme: Theme = {
|
|||
inputInactiveBG: Colors.AQUA_HAZE,
|
||||
textDefault: Colors.BLACK_PEARL,
|
||||
textOnDarkBG: Colors.WHITE,
|
||||
textOnGreyBG: Colors.CHARCOAL,
|
||||
textAnchor: Colors.PURPLE,
|
||||
border: Colors.GEYSER,
|
||||
paneCard: Colors.SHARK,
|
||||
|
|
@ -2748,6 +2749,8 @@ export const theme: Theme = {
|
|||
dropdownIconBg: Colors.ALTO2,
|
||||
welcomeTourStickySidebarColor: Colors.WHITE,
|
||||
welcomeTourStickySidebarBackground: "#F86A2B",
|
||||
dropdownIconDarkBg: Colors.DARK_GRAY,
|
||||
dropdownGreyBg: Colors.Gallery,
|
||||
},
|
||||
|
||||
lineHeights: [0, 14, 16, 18, 22, 24, 28, 36, 48, 64, 80],
|
||||
|
|
|
|||
|
|
@ -63,6 +63,65 @@ function PostBodyData(props: Props) {
|
|||
updateBodyContentType,
|
||||
} = props;
|
||||
|
||||
const tabComponentsMap = (
|
||||
key: string,
|
||||
contentType: ApiContentTypes,
|
||||
): JSX.Element => {
|
||||
return {
|
||||
[ApiContentTypes.JSON]: (
|
||||
<JSONEditorFieldWrapper className={"t--apiFormPostBody"} key={key}>
|
||||
<DynamicTextField
|
||||
dataTreePath={`${dataTreePath}.body`}
|
||||
expected={expectedPostBody}
|
||||
mode={EditorModes.JSON_WITH_BINDING}
|
||||
name="actionConfiguration.body"
|
||||
placeholder={
|
||||
'{\n "name":"{{ inputName.property }}",\n "preference":"{{ dropdownName.property }}"\n}\n\n\\\\Take widget inputs using {{ }}'
|
||||
}
|
||||
showLineNumbers
|
||||
size={EditorSize.EXTENDED}
|
||||
tabBehaviour={TabBehaviour.INDENT}
|
||||
theme={theme}
|
||||
/>
|
||||
</JSONEditorFieldWrapper>
|
||||
),
|
||||
[ApiContentTypes.FORM_URLENCODED]: (
|
||||
<KeyValueFieldArray
|
||||
dataTreePath={`${dataTreePath}.bodyFormData`}
|
||||
key={key}
|
||||
label=""
|
||||
name="actionConfiguration.bodyFormData"
|
||||
theme={theme}
|
||||
/>
|
||||
),
|
||||
|
||||
[ApiContentTypes.MULTIPART_FORM_DATA]: (
|
||||
<KeyValueFieldArray
|
||||
dataTreePath={`${dataTreePath}.bodyFormData`}
|
||||
hasType
|
||||
key={key}
|
||||
label=""
|
||||
name="actionConfiguration.bodyFormData"
|
||||
pushFields
|
||||
theme={theme}
|
||||
/>
|
||||
),
|
||||
|
||||
[ApiContentTypes.RAW]: (
|
||||
<JSONEditorFieldWrapper key={key}>
|
||||
<DynamicTextField
|
||||
dataTreePath={`${dataTreePath}.body`}
|
||||
mode={EditorModes.TEXT_WITH_BINDING}
|
||||
name="actionConfiguration.body"
|
||||
size={EditorSize.EXTENDED}
|
||||
tabBehaviour={TabBehaviour.INDENT}
|
||||
theme={theme}
|
||||
/>
|
||||
</JSONEditorFieldWrapper>
|
||||
),
|
||||
}[contentType];
|
||||
};
|
||||
|
||||
return (
|
||||
<PostBodyContainer>
|
||||
<MultiSwitch
|
||||
|
|
@ -71,54 +130,11 @@ function PostBodyData(props: Props) {
|
|||
}
|
||||
selected={displayFormat}
|
||||
tabs={POST_BODY_FORMAT_TITLES.map((el) => {
|
||||
let component = (
|
||||
<JSONEditorFieldWrapper
|
||||
className={"t--apiFormPostBody"}
|
||||
key={el.key}
|
||||
>
|
||||
<DynamicTextField
|
||||
dataTreePath={`${dataTreePath}.body`}
|
||||
expected={expectedPostBody}
|
||||
mode={EditorModes.JSON_WITH_BINDING}
|
||||
name="actionConfiguration.body"
|
||||
placeholder={
|
||||
'{\n "name":"{{ inputName.property }}",\n "preference":"{{ dropdownName.property }}"\n}\n\n\\\\Take widget inputs using {{ }}'
|
||||
}
|
||||
showLineNumbers
|
||||
size={EditorSize.EXTENDED}
|
||||
tabBehaviour={TabBehaviour.INDENT}
|
||||
theme={theme}
|
||||
/>
|
||||
</JSONEditorFieldWrapper>
|
||||
);
|
||||
if (
|
||||
el.title === ApiContentTypes.FORM_URLENCODED ||
|
||||
el.title === ApiContentTypes.MULTIPART_FORM_DATA
|
||||
) {
|
||||
component = (
|
||||
<KeyValueFieldArray
|
||||
dataTreePath={`${dataTreePath}.bodyFormData`}
|
||||
key={el.key}
|
||||
label=""
|
||||
name="actionConfiguration.bodyFormData"
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
} else if (el.title === ApiContentTypes.RAW) {
|
||||
component = (
|
||||
<JSONEditorFieldWrapper key={el.key}>
|
||||
<DynamicTextField
|
||||
dataTreePath={`${dataTreePath}.body`}
|
||||
mode={EditorModes.TEXT_WITH_BINDING}
|
||||
name="actionConfiguration.body"
|
||||
size={EditorSize.EXTENDED}
|
||||
tabBehaviour={TabBehaviour.INDENT}
|
||||
theme={theme}
|
||||
/>
|
||||
</JSONEditorFieldWrapper>
|
||||
);
|
||||
}
|
||||
return { key: el.key, title: el.title, panelComponent: component };
|
||||
return {
|
||||
key: el.key,
|
||||
title: el.title,
|
||||
panelComponent: tabComponentsMap(el.key, el.title),
|
||||
};
|
||||
})}
|
||||
/>
|
||||
</PostBodyContainer>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user