Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2632,3 +2632,8 @@ export const DATASOURCE_SECURE_TEXT = () =>
export const TABLE_LOADING_RECORDS = () => "loading records";

export const UPCOMING_SAAS_INTEGRATIONS = () => "Upcoming SaaS Integrations";

export const NO_SEARCH_COMMAND_FOUND_EXTERNAL_SAAS = () =>
"No actions match your search";

export const ADD_CUSTOM_ACTION = () => "Add custom action";
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from "react";
import {
ADD_CUSTOM_ACTION,
createMessage,
NO_SEARCH_COMMAND_FOUND_EXTERNAL_SAAS,
} 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("command");
Comment thread
AmanAgarwal041 marked this conversation as resolved.
Outdated

const onClick = () => {
const customActionOption = options.find((option) =>
option.label.toLowerCase().includes("custom action"),
);

if (customActionOption?.value) {
onSelectOptions(customActionOption?.value);
document.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
}
};

if (isExternalSaasPluginCommandDropdown) {
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 kind="secondary" onClick={onClick} size="sm" startIcon="plus">
{createMessage(ADD_CUSTOM_ACTION)}
</Button>
</Flex>
);
}

return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
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";

enum CUSTOM_ACTION_TABS {
HEADERS = "HEADERS",
PARAMS = "PARAMS",
BODY = "BODY",
}

const TabbedControls = (props: ControlProps) => {
return (
<Tabs 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Address TypeScript errors properly

There are multiple @ts-expect-error comments indicating incomplete type definitions for FormControl. Consider creating proper type interfaces or contributing to the existing ones instead of suppressing these errors.

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 app/client/src/pages/Editor/FormControl.tsx) are missing the showHeader property. Please update the FormControlProps interface to include showHeader (and any other missing props), then remove the accompanying @ts-expect-error comments in:

  • app/client/src/components/formControls/CustomActionsConfigControl/index.tsx (lines 59–60)
  • app/client/src/components/formControls/CustomActionsConfigControl/index.tsx (lines 72–74)

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>
</Tabs>
);
};

/**
* 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>
);
}
}
9 changes: 9 additions & 0 deletions app/client/src/components/formControls/DropDownControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
ConditionalOutput,
DynamicValues,
} from "reducers/evaluationReducers/formEvaluationReducer";
import NoSearchCommandFound from "./CustomActionsConfigControl/NoSearchCommandFound";

export interface DropDownGroupedOptions {
label: string;
Expand Down Expand Up @@ -462,6 +463,14 @@ function renderDropdown(
isLoading={props.isLoading}
isMultiSelect={isMultiSelect}
maxTagCount={props.maxTagCount}
notFoundContent={
<NoSearchCommandFound

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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
It is specific to external saas plugin. Any ideas on how we can do it via config ? Because it requires some functionalities as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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={props.formValues.pluginId}
/>
}
onClear={clearAllOptions}
onDeselect={onRemoveOptions}
onPopupScroll={handlePopupScroll}
Expand Down
9 changes: 9 additions & 0 deletions app/client/src/utils/formControl/FormControlRegistry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
} from "components/formControls/SliderControl";
import { HybridSearchControl } from "components/formControls/HybridSearch";
import FunctionCallingConfigControl from "components/formControls/FunctionCallingConfigControl";
import { CustomActionsControl } from "components/formControls/CustomActionsConfigControl";

/**
* NOTE: If you are adding a component that uses FormControl
Expand Down Expand Up @@ -240,6 +241,14 @@ class FormControlRegistry {
},
},
);
FormControlFactory.registerControlBuilder(
formControlTypes.CUSTOM_ACTIONS_CONFIG_FORM,
{
buildPropertyControl(controlProps): JSX.Element {
return <CustomActionsControl {...controlProps} />;
},
},
);
}
}

Expand Down
1 change: 1 addition & 0 deletions app/client/src/utils/formControl/formControlTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export default {
RAG_DOCUMENTS_SELECTOR: "RAG_DOCUMENTS_SELECTOR",
HYBRID_SEARCH: "HYBRID_SEARCH",
FUNCTION_CALLING_CONFIG_FORM: "FUNCTION_CALLING_CONFIG_FORM",
CUSTOM_ACTIONS_CONFIG_FORM: "CUSTOM_ACTIONS_CONFIG_FORM",
};