feat: Enhance Webhook component (#6313)

* 📝 (constants.py): Add "copy_field" attribute to FIELD_FORMAT_ATTRIBUTES list
📝 (webhook.py): Add "copy_field" attribute to MultilineInput component
📝 (input_mixin.py): Add "copy_field" attribute to BaseInputMixin class
📝 (inputs.py): Add "copy_field" attribute to StrInput class
📝 (template/field/base.py): Add "copy_field" attribute to Input class
🚀 (NodeDescription/index.tsx): Remove default placeholder text for emptyPlaceholder prop
✨ (copyFieldAreaComponent/index.tsx): Add new component for handling copy field functionality
♻️ (strRenderComponent/index.tsx): Refactor component to include CopyFieldAreaComponent when copy_field attribute is present in template data

* ✨ (NodeDescription/index.tsx): refactor renderedDescription useMemo to improve readability and maintainability
♻️ (GenericNode/index.tsx): refactor code to improve readability and maintainability, and optimize rendering logic

* 📝 (webhook.py): Add cURL field to WebhookComponent for better integration with external systems
📝 (graph/base.py): Add logging of vertex build information in Graph class for debugging purposes
📝 (NodeInputField/index.tsx): Add nodeInformationMetadata to NodeInputField for better tracking of node information
📝 (copyFieldAreaComponent/index.tsx): Refactor CopyFieldAreaComponent to handle different types of values, including webhooks
📝 (strRenderComponent/index.tsx): Add WebhookFieldComponent to handle webhook type in StrRenderComponent
📝 (tableNodeCellRender/index.tsx): Add nodeInformationMetadata to TableNodeCellRender for better tracking of node information
📝 (textAreaComponent/index.tsx): Add support for webhook format in TextAreaComponent for better integration with webhooks
📝 (webhookFieldComponent/index.tsx): Add WebhookFieldComponent to handle webhook type in ParameterRenderComponent
📝 (custom-parameter.tsx): Add nodeInformationMetadata to CustomParameterComponent for better tracking of node information
📝 (get-curl-code.tsx): Add support for different formats in getCurlWebhookCode for generating cURL commands
📝 (textAreaModal/index.tsx): Add onCloseModal callback to ComponentTextModal for better handling of modal closing
📝 (index.ts): Add type field to APIClassType for better typing of API classes

* ✨ (index.tsx): Add a button to generate a token in the WebhookFieldComponent for improved user experience and functionality. Update the structure of the component to include the new button and styling adjustments.

* [autofix.ci] apply automated fixes

* ✨ (generate-token-dialog.tsx): add GenerateTokenDialog component to handle token generation in webhookFieldComponent
📝 (index.tsx): import and use GenerateTokenDialog component in WebhookFieldComponent for token generation functionality

* ✨ (frontend): introduce new feature to create API keys with customizable modal properties
🔧 (frontend): add modalProps object to customize modal title, description, input label, input placeholder, button text, generated key message, and show icon flag

* add pool interval variable and tests

* 📝 (NodeOutputfield): Remove unused ScanEyeIcon component
✨ (validate-webhook.ts): Add function to validate webhook data before processing
♻️ (use-get-builds-pooling-mutation): Refactor to set flow pool based on current flow
🔧 (content-render.tsx): Add data-testid attribute to api key input element
🔧 (webhookComponent.spec.ts): Refactor test to use waitForRequest for monitoring build requests

* [autofix.ci] apply automated fixes

* 🔧 (backend): rename webhook_pooling_interval to webhook_polling_interval for consistency
🔧 (frontend): update references to webhook_pooling_interval to webhook_polling_interval for consistency

* 📝 (frontend): Update import paths and remove unused imports for better code organization and maintainability
🔧 (frontend): Refactor background styles in components to use constants for consistency and easier theming
🚀 (frontend): Add custom SecretKeyModalButton component for better modularity and reusability

* 📝 (use-get-api-keys.ts): add a TODO comment to request API key from DSLF endpoint for future implementation.

* 📝 (input_mixin.py): Remove copy_field attribute from BaseInputMixin as it is no longer needed
♻️ (inputs.py): Remove copy_field attribute from StrInput class as it is no longer needed
♻️ (inputs.py): Set copy_field attribute to False in MultilineInput class to ensure consistency
♻️ (template/field/base.py): Remove copy_field attribute from Input class as it is no longer needed
📝 (textAreaComponent/index.tsx): Replace hardcoded value "CURL_WEBHOOK" with constant WEBHOOK_VALUE for better readability and maintainability

* 🐛 (base.py): fix issue where flow_id could be None by defaulting to an empty string if flow_id is None

* 🔧 (secret-key-modal.tsx): Remove unused SecretKeyModalButton component
🔧 (get-modal-props.tsx): Remove unused getModalPropsApiKey function and related imports and constants

* 📝 (langflow): add noqa comments to suppress linting rule A005 for specific files in the io, logging, and socket modules

* [autofix.ci] apply automated fixes

* 📝 (frontend): Remove unused endpointName property from NodeInputField component
🔧 (frontend): Add useFlowStore import and use it to get currentFlow and endpointName in CopyFieldAreaComponent, TableNodeCellRender, TextAreaComponent, and WebhookFieldComponent components
🔧 (frontend): Refactor useGetBuildsMutation to handle multiple concurrent requests and prevent duplicate requests

* ✨ (webhookComponent.spec.ts): refactor test to improve readability and maintainability by removing redundant code and focusing on essential test steps
♻️ (userSettings.spec.ts): refactor test to improve readability and maintainability by removing redundant code and focusing on essential test steps

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-03-10 10:10:55 -03:00 • committed by GitHub
commit 94140ccf2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 1155 additions and 182 deletions

View file

@ -0,0 +1,127 @@
import { expect, test } from "@playwright/test";
import { adjustScreenView } from "../../utils/adjust-screen-view";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
test(
"user should be able to create an api key within a webhook component",
{ tag: ["@release", "@workspace"] },
async ({ page }) => {
const randomApiKeyDescription =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
await awaitBootstrapTest(page);
await page.waitForSelector('[data-testid="blank-flow"]', {
timeout: 30000,
});
await page.getByTestId("blank-flow").click();
await page.getByTestId("sidebar-search-input").click();
await page.getByTestId("sidebar-search-input").fill("webhook");
await page.waitForSelector('[data-testid="dataWebhook"]', {
timeout: 3000,
});
await page
.getByTestId("dataWebhook")
.hover()
.then(async () => {
await page.getByTestId("add-component-button-webhook").click();
});
await adjustScreenView(page);
await page
.getByTestId("data_webhook_draggable")
.hover()
.then(async () => {
await page.waitForSelector("text=Webhook already added", {
timeout: 30000,
});
});
await page.getByTestId("btn_copy_str_endpoint").click();
await page.waitForSelector("text=Endpoint URL copied", { timeout: 30000 });
await page.getByTestId("title-Webhook").click();
await page.getByTestId("edit-button-modal").click();
await page
.getByTestId("button_open_text_area_modal_str_edit_curl_advanced")
.click();
const curl = await page.getByTestId("text-area-modal").inputValue();
const currentUrl = page.url();
const flowId = currentUrl.split("/")[2];
expect(curl).toContain(flowId);
},
);
test(
"user should be able to poll a webhook",
{ tag: ["@release", "@workspace"] },
async ({ page, request }) => {
await page.route("**/api/v1/config", (route) => {
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
webhook_polling_interval: 1000,
}),
headers: {
"content-type": "application/json",
...route.request().headers(),
},
});
});
const randomApiKeyDescription =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
await awaitBootstrapTest(page);
await page.waitForSelector('[data-testid="blank-flow"]', {
timeout: 30000,
});
await page.getByTestId("blank-flow").click();
await page.getByTestId("sidebar-search-input").click();
await page.getByTestId("sidebar-search-input").fill("webhook");
await page.waitForSelector('[data-testid="dataWebhook"]', {
timeout: 3000,
});
await page
.getByTestId("dataWebhook")
.hover()
.then(async () => {
await page.getByTestId("add-component-button-webhook").click();
});
await adjustScreenView(page);
await page
.getByTestId("data_webhook_draggable")
.hover()
.then(async () => {
await page.waitForSelector("text=Webhook already added", {
timeout: 30000,
});
});
await page.getByTestId("btn_copy_str_endpoint").click();
await page.waitForSelector("text=Endpoint URL copied", { timeout: 30000 });
const monitorBuildPromise = page.waitForRequest((request) =>
request.url().includes("/monitor/build"),
);
const monitorBuildRequest = await monitorBuildPromise;
expect(monitorBuildRequest).toBeTruthy();
},
);