-
Notifications
You must be signed in to change notification settings - Fork 4.5k
feat: added custom action config control type for paragon integrations #39764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
79e2bdc
817da68
6263dad
f82ed56
acc75be
d7d679c
348b407
2f2120d
e6f50bf
6ab4d0d
748f2e4
5d230c5
73a1906
aacec72
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| import React from "react"; | ||
| import { | ||
| ADD_CUSTOM_ACTION, | ||
| CONFIG_PROPERTY_COMMAND, | ||
| createMessage, | ||
| CUSTOM_ACTION_LABEL, | ||
| NO_SEARCH_COMMAND_FOUND_EXTERNAL_SAAS, | ||
| NOT_FOUND, | ||
| } from "ee/constants/messages"; | ||
| import { Button, Flex, Text, type SelectOptionProps } from "@appsmith/ads"; | ||
| import { useSelector } from "react-redux"; | ||
| import { getPlugin } from "ee/selectors/entitiesSelector"; | ||
| import { PluginType, type Plugin } from "entities/Plugin"; | ||
| export default function NoSearchCommandFound({ | ||
| configProperty, | ||
| onSelectOptions, | ||
| options, | ||
| pluginId, | ||
| }: { | ||
| configProperty: string; | ||
| onSelectOptions: (optionValueToSelect: string) => void; | ||
| options: SelectOptionProps[]; | ||
| pluginId?: string; | ||
| }) { | ||
| const plugin: Plugin | undefined = useSelector((state) => | ||
| getPlugin(state, pluginId || ""), | ||
| ); | ||
|
|
||
| const isExternalSaasPluginCommandDropdown = | ||
| plugin?.type === PluginType.EXTERNAL_SAAS && | ||
| configProperty.includes(createMessage(CONFIG_PROPERTY_COMMAND)); | ||
|
|
||
| const customActionOption = options.find((option) => | ||
| option.label | ||
| .toLowerCase() | ||
| .includes(createMessage(CUSTOM_ACTION_LABEL).toLowerCase()), | ||
| ); | ||
|
|
||
| const onClick = () => { | ||
| onSelectOptions(customActionOption!.value); | ||
| document.dispatchEvent(new MouseEvent("mousedown", { bubbles: true })); | ||
| }; | ||
|
|
||
| if (isExternalSaasPluginCommandDropdown && customActionOption) { | ||
| return ( | ||
| <Flex | ||
| alignItems="center" | ||
| flexDirection={"column"} | ||
| gap="spaces-5" | ||
| padding="spaces-7" | ||
| > | ||
| <Text color="var(--ads-v2-color-gray-500)"> | ||
| {createMessage(NO_SEARCH_COMMAND_FOUND_EXTERNAL_SAAS)} | ||
| </Text> | ||
| <Button | ||
| data-testid="t--select-custom--action" | ||
| kind="secondary" | ||
| onClick={onClick} | ||
| size="sm" | ||
| startIcon="plus" | ||
| > | ||
| {createMessage(ADD_CUSTOM_ACTION)} | ||
| </Button> | ||
| </Flex> | ||
| ); | ||
| } | ||
|
|
||
| return <>{createMessage(NOT_FOUND)}</>; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| import React from "react"; | ||
| import type { ControlType } from "constants/PropertyControlConstants"; | ||
| import FormControl from "pages/Editor/FormControl"; | ||
| import { Grid, Tabs, TabPanel, TabsList, Tab, Flex } from "@appsmith/ads"; | ||
| import BaseControl, { type ControlProps } from "../BaseControl"; | ||
| import { HTTP_METHOD } from "PluginActionEditor/constants/CommonApiConstants"; | ||
| import { API_EDITOR_TAB_TITLES } from "ee/constants/messages"; | ||
| import { createMessage } from "ee/constants/messages"; | ||
| import styled from "styled-components"; | ||
|
|
||
| enum CUSTOM_ACTION_TABS { | ||
| HEADERS = "HEADERS", | ||
| PARAMS = "PARAMS", | ||
| BODY = "BODY", | ||
| } | ||
|
|
||
| const TabbedWrapper = styled(Tabs)` | ||
| .t--form-control-KEYVALUE_ARRAY { | ||
| & > div { | ||
| margin-bottom: var(--ads-v2-spaces-3); | ||
| & > * { | ||
| flex-grow: 1; | ||
| } | ||
| & > *:first-child { | ||
| max-width: 184px; | ||
| } | ||
| & > *:nth-child(2) { | ||
| margin-left: var(--ads-v2-spaces-3); | ||
| } | ||
| & > .t--delete-field { | ||
| max-width: 34px; | ||
| } | ||
| } | ||
| & .t--add-field { | ||
| height: 24px; | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| const TabbedControls = (props: ControlProps) => { | ||
| return ( | ||
| <TabbedWrapper defaultValue={CUSTOM_ACTION_TABS.HEADERS}> | ||
| <TabsList> | ||
| {Object.values(CUSTOM_ACTION_TABS).map((tab) => ( | ||
| <Tab data-testid={`t--api-editor-${tab}`} key={tab} value={tab}> | ||
| {createMessage(API_EDITOR_TAB_TITLES[tab])} | ||
| </Tab> | ||
| ))} | ||
| </TabsList> | ||
|
|
||
| <TabPanel value={CUSTOM_ACTION_TABS.HEADERS}> | ||
| <FormControl | ||
| config={{ | ||
| controlType: "KEYVALUE_ARRAY", | ||
| configProperty: `${props.configProperty}.headers`, | ||
| formName: props.formName, | ||
| id: `${props.configProperty}.headers`, | ||
| isValid: true, | ||
| // @ts-expect-error FormControl component has incomplete TypeScript definitions for some valid properties | ||
| showHeader: true, | ||
|
Comment on lines
+59
to
+60
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainAddress TypeScript errors properly There are multiple Also applies to: 72-74 🏁 Script executed: #!/bin/bash
# Check FormControl type definitions to understand what's missing
fd FormControl --type file --exec grep -l "interface.*FormControlProps" {}Length of output: 124 Update FormControl types to remove the need for error suppression It looks like the FormControl component’s TypeScript definitions (defined in
This change will ensure TypeScript accurately validates the component without suppressing errors. |
||
| }} | ||
| formName={props.formName} | ||
| /> | ||
| </TabPanel> | ||
| <TabPanel value={CUSTOM_ACTION_TABS.PARAMS}> | ||
| <FormControl | ||
| config={{ | ||
| controlType: "KEYVALUE_ARRAY", | ||
| configProperty: `${props.configProperty}.params`, | ||
| formName: props.formName, | ||
| id: `${props.configProperty}.params`, | ||
| // @ts-expect-error FormControl component has incomplete TypeScript definitions for some valid properties | ||
| showHeader: true, | ||
| isValid: true, | ||
| }} | ||
| formName={props.formName} | ||
| /> | ||
| </TabPanel> | ||
| <TabPanel value={CUSTOM_ACTION_TABS.BODY}> | ||
| <FormControl | ||
| config={{ | ||
| controlType: "QUERY_DYNAMIC_TEXT", | ||
| configProperty: `${props.configProperty}.body`, | ||
| formName: props.formName, | ||
| id: `${props.configProperty}.body`, | ||
| label: "", | ||
| isValid: true, | ||
| }} | ||
| formName={props.formName} | ||
| /> | ||
| </TabPanel> | ||
| </TabbedWrapper> | ||
| ); | ||
| }; | ||
|
|
||
| /** | ||
| * This component is used to configure the custom actions for the external integration. | ||
| * It allows the user to add or update details for the custom action like method type, path, headers, params, body. | ||
| */ | ||
| export class CustomActionsControl extends BaseControl<ControlProps> { | ||
| getControlType(): ControlType { | ||
| return "CUSTOM_ACTIONS_CONFIG_FORM"; | ||
| } | ||
| render() { | ||
| const { props } = this; | ||
|
|
||
| return ( | ||
| <Flex flexDirection="column" gap="spaces-4"> | ||
| <Grid gap="spaces-4" gridTemplateColumns="100px 1fr"> | ||
| <FormControl | ||
| config={{ | ||
| controlType: "DROP_DOWN", | ||
| configProperty: `${props.configProperty}.method`, | ||
| formName: props.formName, | ||
| id: `${props.configProperty}.method`, | ||
| label: "", | ||
| isValid: true, | ||
| // @ts-expect-error FormControl component has incomplete TypeScript definitions for some valid properties | ||
| options: Object.values(HTTP_METHOD).map((method) => ({ | ||
| label: method, | ||
| value: method, | ||
| })), | ||
| }} | ||
| formName={props.formName} | ||
| /> | ||
| <FormControl | ||
| config={{ | ||
| controlType: "QUERY_DYNAMIC_INPUT_TEXT", | ||
| configProperty: `${props.configProperty}.path`, | ||
| formName: props.formName, | ||
| id: `${props.configProperty}.path`, | ||
| label: "", | ||
| isValid: true, | ||
| placeholderText: "/v1/users", | ||
| }} | ||
| formName={props.formName} | ||
| /> | ||
| </Grid> | ||
| <TabbedControls {...props} /> | ||
| </Flex> | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ import type { | |
| ConditionalOutput, | ||
| DynamicValues, | ||
| } from "reducers/evaluationReducers/formEvaluationReducer"; | ||
| import NoSearchCommandFound from "./CustomActionsConfigControl/NoSearchCommandFound"; | ||
|
|
||
| export interface DropDownGroupedOptions { | ||
| label: string; | ||
|
|
@@ -462,6 +463,14 @@ function renderDropdown( | |
| isLoading={props.isLoading} | ||
| isMultiSelect={isMultiSelect} | ||
| maxTagCount={props.maxTagCount} | ||
| notFoundContent={ | ||
| <NoSearchCommandFound | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AmanAgarwal041 Is it possible to make this config driven? Asking because this notContentFound is not very generic, it's very specific to external saas plugin but DropdownControl is actually generic
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sneha122 If you see the implementation of this : https://github.com/appsmithorg/appsmith/pull/39764/files#diff-dec54d51495715bd2faf9ea73dc09419fc8e14da8577fadab3fa09878df6bdc5R40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that's true, even passing this component in notContentFound is specific to external saas plugin. Doing it via config would also be tricky, we can probably have component name in the config but the options and what happens on select etc can't be passed through config.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hence, going ahead with the current implementation. @sneha122 |
||
| configProperty={props.configProperty} | ||
| onSelectOptions={onSelectOptions} | ||
| options={options} | ||
| pluginId={get(props.formValues, "pluginId")} | ||
| /> | ||
| } | ||
| onClear={clearAllOptions} | ||
| onDeselect={onRemoveOptions} | ||
| onPopupScroll={handlePopupScroll} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify import path for API_EDITOR_TAB_TITLES
The import statement uses
ee/constants/messagesforAPI_EDITOR_TAB_TITLES, but the provided context shows this constant is defined inapp/client/src/ce/constants/messages.ts. Ensure the import path is correct.🏁 Script executed:
Length of output: 165
Below is a revised review comment after noting that the initial regex search failed. I've generated an updated shell script to re-check the definition (please run it to obtain additional details), and based on the inconclusive automated output, I'm flagging this for manual verification.
Action Required: Verify the Import Path for API_EDITOR_TAB_TITLES
The current code imports
API_EDITOR_TAB_TITLESfromee/constants/messages. However, context suggests it may be defined inapp/client/src/ce/constants/messages.ts. Please verify the actual definition location and update the import path if necessary.To assist further, please run the script below:
API_EDITOR_TAB_TITLESis actually defined inapp/client/src/ce/constants/messages.ts.app/client/src/components/formControls/CustomActionsConfigControl/index.tsxaccordingly if needed.🏁 Script executed:
Length of output: 683
Action Required: Correct Import Path for API_EDITOR_TAB_TITLES
app/client/src/ce/constants/messages.ts(confirmed via grep).app/client/src/components/formControls/CustomActionsConfigControl/index.tsxuses"ee/constants/messages". Update this to reference the correct path.