feat: Clear handles from advanced fields on code update (#8754)
* ✨ (frontend): add new function clearHandlesFromAdvancedFields to handle clearing handles from advanced fields when code is updated 📝 (frontend): update documentation and add tests for deleting handles from advanced fields when code is updated 🔧 (frontend): remove unused style for Outlook in styleUtils to clean up code 🔧 (frontend): add test for deleting handles from advanced fields when code is updated in general-bugs-delete-handle-advanced-input.spec * ✨ (frontend): add support for managing edges and nodes in the flowStore to improve data handling and flow visualization ♻️ (frontend): refactor cleanEdges function to accept an object with nodes, edges, componentId, and data parameters for better modularity and reusability * ✨ (codeAreaModal/index.tsx): Refactor import statements and function names for better clarity and organization ♻️ (flowStore.ts): Refactor cleanEdges function to accept nodes and edges as separate arguments instead of an object ♻️ (flowStore.ts): Update all calls to cleanEdges function to pass nodes and edges separately ♻️ (reactflowUtils.ts): Refactor clearHandlesFromAdvancedFields function to accept only necessary arguments and remove unnecessary logic
This commit is contained in:
parent
04f8f90649
commit
65b71bec5b
4 changed files with 132 additions and 3 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { usePostValidateCode } from "@/controllers/API/queries/nodes/use-post-validate-code";
|
import { usePostValidateCode } from "@/controllers/API/queries/nodes/use-post-validate-code";
|
||||||
import { usePostValidateComponentCode } from "@/controllers/API/queries/nodes/use-post-validate-component-code";
|
import { usePostValidateComponentCode } from "@/controllers/API/queries/nodes/use-post-validate-component-code";
|
||||||
import useFlowStore from "@/stores/flowStore";
|
import { clearHandlesFromAdvancedFields } from "@/utils/reactflowUtils";
|
||||||
import "ace-builds/src-noconflict/ace";
|
import "ace-builds/src-noconflict/ace";
|
||||||
import "ace-builds/src-noconflict/ext-language_tools";
|
import "ace-builds/src-noconflict/ext-language_tools";
|
||||||
import "ace-builds/src-noconflict/ext-searchbox";
|
import "ace-builds/src-noconflict/ext-searchbox";
|
||||||
|
|
@ -83,7 +83,6 @@ export default function CodeAreaModal({
|
||||||
});
|
});
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setValue(code);
|
setValue(code);
|
||||||
// setValue(code);
|
|
||||||
} else {
|
} else {
|
||||||
if (funcErrors.length !== 0) {
|
if (funcErrors.length !== 0) {
|
||||||
setErrorData({
|
setErrorData({
|
||||||
|
|
@ -121,6 +120,8 @@ export default function CodeAreaModal({
|
||||||
onSuccess: ({ data, type }) => {
|
onSuccess: ({ data, type }) => {
|
||||||
if (data && type) {
|
if (data && type) {
|
||||||
setValue(code);
|
setValue(code);
|
||||||
|
clearHandlesFromAdvancedFields(componentId!, data);
|
||||||
|
|
||||||
setNodeClass(data, type);
|
setNodeClass(data, type);
|
||||||
setError({ detail: { error: undefined, traceback: undefined } });
|
setError({ detail: { error: undefined, traceback: undefined } });
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|
@ -255,6 +256,7 @@ export default function CodeAreaModal({
|
||||||
type="submit"
|
type="submit"
|
||||||
id="checkAndSaveBtn"
|
id="checkAndSaveBtn"
|
||||||
disabled={readonly}
|
disabled={readonly}
|
||||||
|
data-testid="checkAndSaveBtn"
|
||||||
>
|
>
|
||||||
Check & Save
|
Check & Save
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,45 @@ export function cleanEdges(nodes: AllNodeType[], edges: EdgeType[]) {
|
||||||
return newEdges;
|
return newEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearHandlesFromAdvancedFields(
|
||||||
|
componentId: string,
|
||||||
|
data: APIClassType,
|
||||||
|
): void {
|
||||||
|
if (!componentId || !data?.template) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const flowStore = useFlowStore.getState();
|
||||||
|
const { edges, deleteEdge } = flowStore;
|
||||||
|
|
||||||
|
const connectedEdges = edges.filter((edge) => edge.target === componentId);
|
||||||
|
|
||||||
|
if (connectedEdges.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const edgeIdsToDelete: string[] = [];
|
||||||
|
|
||||||
|
for (const edge of connectedEdges) {
|
||||||
|
const fieldName = edge.data?.targetHandle?.fieldName;
|
||||||
|
|
||||||
|
if (fieldName && isAdvancedField(data, fieldName)) {
|
||||||
|
edgeIdsToDelete.push(edge.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeIdsToDelete.forEach(deleteEdge);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error clearing handles from advanced fields:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAdvancedField = (data: APIClassType, fieldName: string): boolean => {
|
||||||
|
const field = data.template[fieldName];
|
||||||
|
return field && "advanced" in field && field.advanced === true;
|
||||||
|
};
|
||||||
|
|
||||||
export function filterHiddenFieldsEdges(
|
export function filterHiddenFieldsEdges(
|
||||||
edge: EdgeType,
|
edge: EdgeType,
|
||||||
newEdges: EdgeType[],
|
newEdges: EdgeType[],
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,6 @@ export const SIDEBAR_CATEGORIES = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SIDEBAR_BUNDLES = [
|
export const SIDEBAR_BUNDLES = [
|
||||||
{ display_name: "Outlook", name: "outlook", icon: "Outlook" },
|
|
||||||
{
|
{
|
||||||
display_name: "Language Models",
|
display_name: "Language Models",
|
||||||
name: "languagemodels",
|
name: "languagemodels",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||||
|
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||||
|
import { zoomOut } from "../../utils/zoom-out";
|
||||||
|
|
||||||
|
test(
|
||||||
|
"the system must delete the handles from advanced fields when the code is updated",
|
||||||
|
{ tag: ["@release"] },
|
||||||
|
async ({ page }) => {
|
||||||
|
await awaitBootstrapTest(page);
|
||||||
|
|
||||||
|
await page.getByTestId("blank-flow").click();
|
||||||
|
|
||||||
|
await page.waitForSelector('[data-testid="fit_view"]', {
|
||||||
|
timeout: 100000,
|
||||||
|
});
|
||||||
|
await page.getByTestId("sidebar-search-input").click();
|
||||||
|
await page.getByTestId("sidebar-search-input").fill("if else");
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByTestId("logicIf-Else")
|
||||||
|
.hover()
|
||||||
|
.then(async () => {
|
||||||
|
await page.getByTestId("add-component-button-if-else").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.getByTestId("fit_view").click();
|
||||||
|
await zoomOut(page, 3);
|
||||||
|
|
||||||
|
await page.getByTestId("edit-button-modal").click();
|
||||||
|
|
||||||
|
await page.getByTestId("showmessage").click();
|
||||||
|
|
||||||
|
await page.getByText("Close").last().click();
|
||||||
|
|
||||||
|
await page.getByTestId("sidebar-search-input").click();
|
||||||
|
await page.getByTestId("sidebar-search-input").fill("text input");
|
||||||
|
await page.waitForSelector('[data-testid="input_outputText Input"]', {
|
||||||
|
timeout: 2000,
|
||||||
|
});
|
||||||
|
await page
|
||||||
|
.getByTestId("input_outputText Input")
|
||||||
|
.dragTo(page.locator('//*[@id="react-flow-id"]'), {
|
||||||
|
targetPosition: { x: 200, y: 100 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByTestId("handle-textinput-shownode-output text-right")
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByTestId("handle-conditionalrouter-shownode-alternative output-left")
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page.getByTestId("title-If-Else").click();
|
||||||
|
|
||||||
|
await page.getByTestId("edit-button-modal").click();
|
||||||
|
|
||||||
|
const numberOfDisabledInputs = await page
|
||||||
|
.getByPlaceholder("Receiving input")
|
||||||
|
.count();
|
||||||
|
|
||||||
|
expect(numberOfDisabledInputs).toBe(2);
|
||||||
|
|
||||||
|
const numberOfLockIcons = await page.getByTestId("icon-lock").count();
|
||||||
|
|
||||||
|
expect(numberOfLockIcons).toBe(2);
|
||||||
|
|
||||||
|
await page.getByText("Close").last().click();
|
||||||
|
|
||||||
|
await page.getByTestId("title-If-Else").click();
|
||||||
|
|
||||||
|
await page.getByTestId("code-button-modal").click();
|
||||||
|
|
||||||
|
await page.getByTestId("checkAndSaveBtn").last().click();
|
||||||
|
|
||||||
|
await page.getByTestId("edit-button-modal").click();
|
||||||
|
|
||||||
|
const numberOfDisabledInputsAfter = await page
|
||||||
|
.getByPlaceholder("Receiving input")
|
||||||
|
.count();
|
||||||
|
|
||||||
|
expect(numberOfDisabledInputsAfter).toBe(0);
|
||||||
|
|
||||||
|
const numberOfLockIconsAfter = await page.getByTestId("icon-lock").count();
|
||||||
|
|
||||||
|
expect(numberOfLockIconsAfter).toBe(0);
|
||||||
|
},
|
||||||
|
);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue