Skip to content

Workflow template GitHub PR -> Confluence Doc#237

Open
Zingzy wants to merge 5 commits into
potpie-ai:mainfrom
Zingzy:workflow-template-1
Open

Workflow template GitHub PR -> Confluence Doc#237
Zingzy wants to merge 5 commits into
potpie-ai:mainfrom
Zingzy:workflow-template-1

Conversation

@Zingzy

@Zingzy Zingzy commented Dec 2, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Jira workflow trigger to start workflows when issues are created in Jira.
    • Added Confluence integration for creating pages and accessing documentation within workflows.
    • Added Slack integration to send messages directly from workflows.
    • Added new PR Merged → Documentation Generator workflow template.
  • Bug Fixes

    • Enhanced workflow title handling with sanitization and default naming for empty titles.

✏️ Tip: You can customize this high-level summary in your review settings.

…t selectors, and include a new example workflow.
…e to support workflow agents, and enhance color utilities for new node types
…and space selectors, enhancing configuration handling
@coderabbitai

coderabbitai Bot commented Dec 2, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This PR introduces Jira, Confluence, and Slack integrations into the workflow editor with new trigger and action nodes, alongside a Confluence Documentation Agent. It extends agent and integration services to include workflow-related metadata, adds integration selector components, and updates the node registry and rendering pipeline to support the new node types.

Changes

Cohort / File(s) Summary
Agent & Workflow Context
app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx, app/(main)/workflows/components/editor/hooks/useWorkflowEditor.ts, app/(main)/workflows/components/editor/nodes/agents/agent.tsx
Updated agent fetching to include workflow agents via new includeWorkflowAgents parameter; added agent fields is_workflow_agent and requires_repo_context; implemented agent filtering logic to separate system/workflow agents from user-available agents; added title sanitization (trim and default to "Untitled Workflow") in workflow save payload.
Confluence Integration
app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx, app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx, app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx, app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx
Added ConfluenceCreatePageNode action for workflow page creation; introduced ConfluenceIntegrationSelector and ConfluenceSpaceSelector UI components; added ConfluenceAgentConfigComponent and ConfluenceAgentNode for a Confluence Documentation Agent with task description input.
Jira Integration
app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx, app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx, app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx
Introduced JiraTriggerNode for Jira issue creation triggers with webhook state checking; added JiraIntegrationSelector and JiraProjectSelector components for integration and project filtering; includes webhook setup guidance and JQL/project-based filtering configuration.
Slack Integration
app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx
Added SlackSendMessageNode action node with configuration component for channel selection and message composition.
Node Infrastructure & Registry
app/(main)/workflows/components/editor/nodes/color_utils.ts, app/(main)/workflows/components/editor/nodes/index.ts, app/(main)/workflows/components/editor/nodes/node-registry.ts, app/(main)/workflows/components/editor/nodes/node.tsx, app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx
Expanded NodeGroup type and color palettes to support jira, confluence, and slack; added NodeType and NodeCategory variants for new integrations; registered new node metadata in availableNodes; extended node rendering logic with switch cases for trigger_jira_issue_created, action_confluence_create_page, action_slack_send_message, and system_workflow_agent_confluence.
Service Layer
services/AgentService.ts, services/IntegrationService.ts, services/WorkflowService.ts
Extended AgentService.getAgentList with optional includeWorkflowAgents parameter; added metadata and webhooks fields to ConnectedIntegration types; introduced getJiraProjects method to fetch available Jira projects; expanded NodeType, NodeGroup, and NodeCategory type unions.
Workflow Page & Templates
app/(main)/workflows/page.tsx
Added new template "PR Merged → Documentation Generator" with Confluence agent task; updated agent fetching to include workflow agents; implemented agent name mapping for system workflow agents; added debug logging for agent fetch results.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Webhook state management: JiraTriggerConfigComponent contains stateful webhook handling with URL construction and effect dependencies that requires careful verification.
  • Agent filtering logic: The separation of system/workflow agents from user-available agents in agent.tsx and page.tsx involves filtering logic that impacts node availability.
  • Configuration propagation: New components (ConfluenceConfigComponent, SlackConfigComponent, JiraTriggerConfigComponent) propagate config changes through callbacks; ensure onConfigChange handlers are correctly wired.
  • Integration with node rendering: Verify that new node types are correctly routed through the expanded switch logic in node.tsx and trigger.tsx.
  • Service parameter contracts: Confirm that new parameters (includeWorkflowAgents, new query params in IntegrationService) align across callers and API expectations.

Possibly related PRs

  • Feat/wf revamp #202: Modifies AgentDataContext and agent fetching logic, updating the same agent service calls and context provider for workflow agents.
  • feat: workflow editor #196: Implements the core workflow editor feature set including Jira/Confluence/Slack node definitions and service integrations.
  • feat: integrations page #215: Extends IntegrationService types and integration client components with ConnectedIntegration metadata and Jira project fetching.

Suggested reviewers

  • nndn
  • dhirenmathur

🐰 Hops through the workflow nodes with glee!

New integrations bloom—Jira, Confluence, Slack so bright,
Agents dance and selectors pick with delight,
Workflows now connected, from trigger to action's flight!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Workflow template GitHub PR -> Confluence Doc' accurately summarizes the main change: adding a new workflow template that triggers on GitHub PR merged events and generates Confluence documentation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud

sonarqubecloud Bot commented Dec 2, 2025

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
8.9% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 10

🧹 Nitpick comments (21)
app/(main)/workflows/components/editor/hooks/useWorkflowEditor.ts (1)

963-963: LGTM! Good defensive coding for title sanitization.

The title trimming and fallback to "Untitled Workflow" ensures that empty or whitespace-only titles are handled gracefully when persisting workflows. Since this payload is used by both create and update operations, the sanitization applies consistently across both paths.

Optional: Consider sanitizing in onTitleChange as well.

The onTitleChange handler (line 770) currently updates the title directly without sanitization. While deferring sanitization to the save boundary is valid, applying .trim() in onTitleChange could provide more immediate feedback to users and keep the local state cleaner.

If desired, apply this diff to add consistent sanitization:

 const onTitleChange = useCallback(
   (newTitle: string) => {
-    const updatedWorkflow = { ...localWorkflow, title: newTitle };
+    const updatedWorkflow = { ...localWorkflow, title: newTitle.trim() };
     updateLocalWorkflow(updatedWorkflow, true);
   },
   [localWorkflow, updateLocalWorkflow]
 );
app/(main)/workflows/components/editor/nodes/agents/agent.tsx (2)

50-56: Consider simplifying the effect dependency array.

Since availableAgents is derived from allAgents via filtering, you could simplify the dependency array to just [allAgents.length]. The current implementation is correct but slightly redundant.

Apply this diff to simplify:

-  }, [availableAgents.length, allAgents.length]);
+  }, [allAgents.length]);

316-316: Consider renaming for consistency.

For consistency with AgentConfigComponent (line 37), consider renaming agents to allAgents here as well. This makes it clearer that you're working with the complete agent list.

Apply this diff:

-  const { agents } = useAgentData();
+  const { agents: allAgents } = useAgentData();

Then update line 326:

-  const resolvedAgent = agentId ? agents.find((a) => a.id === agentId) : null;
+  const resolvedAgent = agentId ? allAgents.find((a) => a.id === agentId) : null;
app/(main)/workflows/page.tsx (1)

301-309: Use a Set for agentTypes for more efficient lookup.

Per static analysis, using Set.has() is more performant than Array.includes() for membership checks.

-    const agentTypes = [
-      "custom_agent",
-      "action_agent",
-      "system_workflow_agent_confluence",
-    ];
-    const agentNodes = Object.values(workflow.graph.nodes).filter((node) =>
-      agentTypes.includes(node.type)
-    );
+    const agentTypes = new Set([
+      "custom_agent",
+      "action_agent",
+      "system_workflow_agent_confluence",
+    ]);
+    const agentNodes = Object.values(workflow.graph.nodes).filter((node) =>
+      agentTypes.has(node.type)
+    );
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx (3)

21-24: Mark props interface as read-only.

Using Readonly for props improves type safety by preventing accidental mutation.

-interface ConfluenceIntegrationSelectorProps {
-    selectedIntegrationId: string | null;
-    onIntegrationChange: (integrationId: string, cloudId: string) => void;
-}
+interface ConfluenceIntegrationSelectorProps {
+    readonly selectedIntegrationId: string | null;
+    readonly onIntegrationChange: (integrationId: string, cloudId: string) => void;
+}

78-87: Associate label with control for accessibility.

The label on line 81 is not associated with any form control. While this is an error state display without an interactive control, consider using a different semantic element.

 if (error) {
     return (
         <div className="space-y-2">
-            <label className="text-sm font-medium">Confluence Workspace</label>
+            <span className="text-sm font-medium">Confluence Workspace</span>
             <div className="flex items-center gap-2 p-3 border rounded-md bg-destructive/10">
                 <span className="text-sm text-destructive">{error}</span>
             </div>
         </div>
     );
 }

89-91: Associate label with control for accessibility.

Similar to the error state, this label at line 91 should be associated with the popover trigger button using htmlFor and matching id, or use a different semantic element since this is a custom combobox pattern.

 <div className="space-y-2">
-    <label className="text-sm font-medium">Confluence Workspace</label>
+    <span className="text-sm font-medium" id="confluence-workspace-label">Confluence Workspace</span>
     <Popover open={open} onOpenChange={setOpen}>
         <PopoverTrigger asChild>
             ...
                 <Button
                     variant="outline"
                     role="combobox"
                     aria-expanded={open}
+                    aria-labelledby="confluence-workspace-label"
                     className="w-full justify-between"
                 >
app/(main)/workflows/components/editor/nodes/node.tsx (1)

39-48: Improve fallback UI for unknown action types.

The fallback <div>Unknown action type</div> is minimal and could confuse users. Consider adding styling consistent with the node UI or logging a warning for debugging.

     case "action":
       // Handle different action types
       switch (data.type) {
         case "action_confluence_create_page":
           return <ConfluenceCreatePageNode data={data} />;
         case "action_slack_send_message":
           return <SlackSendMessageNode data={data} />;
         default:
-          return <div>Unknown action type</div>;
+          return (
+            <div className="p-4 text-center text-muted-foreground">
+              <span className="text-sm">Unknown action type: {data.type}</span>
+            </div>
+          );
       }
app/(main)/workflows/components/editor/nodes/node-registry.ts (1)

88-102: Missing re-exports for new node metadata.

confluenceCreatePageNodeMetadata and slackSendMessageNodeMetadata are imported and added to availableNodes but not included in the explicit re-export block. Add them for consistency if direct imports are needed elsewhere.

 export {
   prOpenedTriggerNodeMetadata,
   prClosedTriggerNodeMetadata,
   prReopenedTriggerNodeMetadata,
   prMergedTriggerNodeMetadata,
   issueAddedTriggerNodeMetadata,
   linearTriggerNodeMetadata,
   jiraTriggerNodeMetadata,
   issueCreatedTriggerNodeMetadata,
   webhookTriggerNodeMetadata,
   agentNodeMetadata,
   actionAgentNodeMetadata,
   ifConditionNodeMetadata,
   confluenceAgentNodeMetadata,
+  confluenceCreatePageNodeMetadata,
+  slackSendMessageNodeMetadata,
 };
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx (3)

43-46: Remove debug console.log statements before merging.

These logging statements are useful during development but should be removed for production code to avoid cluttering browser console output.

-    console.log(
-        "JiraIntegrationSelector render with selectedIntegrationId:",
-        selectedIntegrationId
-    );

And remove the logs inside handleIntegrationChange:

-            console.log(
-                "JiraIntegrationSelector handleIntegrationChange called with:",
-                integrationId
-            );
             // Find the integration to get the unique identifier
             const integration = integrations.find((int) => int.id === integrationId);
             const uniqueIdentifier = integration?.uniqueIdentifier;
-            console.log("JiraIntegrationSelector found integration:", integration);
-            console.log(
-                "JiraIntegrationSelector uniqueIdentifier:",
-                uniqueIdentifier
-            );

Also applies to: 59-70


154-193: Extract nested ternary into helper function or separate components for readability.

The nested ternary operator makes this code difficult to read and maintain. SonarCloud also flags this pattern.

Consider extracting the button rendering logic:

const renderTriggerButton = () => {
    if (loading) {
        return (
            <Button
                className="flex gap-3 items-center font-semibold justify-start w-full"
                variant="outline"
                disabled
            >
                <Loader2 className="h-4 w-4 text-[#7A7A7A] animate-spin" strokeWidth={1.5} />
                Loading Jira integrations...
            </Button>
        );
    }

    const buttonStyle = readOnly ? { pointerEvents: "none" as const } : {};
    const icon = <Ticket className="h-4 w-4 text-[#7A7A7A]" strokeWidth={1.5} />;

    if (!hasSelectedIntegration) {
        return (
            <Button className="flex gap-3 items-center font-semibold justify-start w-full" variant="outline" style={buttonStyle}>
                {icon}
                Select Jira Integration
            </Button>
        );
    }

    return (
        <Button className="flex gap-3 items-center font-semibold justify-start w-full" variant="outline" style={buttonStyle}>
            {icon}
            <span className="truncate text-ellipsis whitespace-nowrap">
                {selectedIntegration?.name || `Integration ${selectedIntegrationId}`}
            </span>
        </Button>
    );
};

38-42: Use FC type annotation for consistency with coding guidelines.

Per the coding guidelines, functional components should use TypeScript FC types.

+import { FC } from "react";
+
-export const JiraIntegrationSelector = ({
+export const JiraIntegrationSelector: FC<JiraIntegrationSelectorProps> = ({
     selectedIntegrationId,
     onIntegrationChange,
     readOnly = false,
-}: JiraIntegrationSelectorProps) => {
+}) => {
app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx (1)

7-11: Define a proper interface for the Slack config instead of using any.

Using any for the config type loses TypeScript's type safety benefits and makes it harder to catch errors at compile time.

+interface SlackConfig {
+    connection_id?: string;
+    channel_id?: string;
+    message?: string;
+}
+
 interface SlackConfigProps {
-    config: any;
-    onConfigChange: (config: any) => void;
+    config: SlackConfig;
+    onConfigChange: (config: SlackConfig) => void;
     readOnly?: boolean;
 }
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx (1)

53-86: Consider using IntegrationService for API calls to maintain consistency.

Other components in this PR (e.g., JiraIntegrationSelector, JiraProjectSelector) use IntegrationService for API calls. Using axios directly here breaks the abstraction and makes it harder to apply consistent error handling, caching, or authentication logic.

Consider adding a getConfluenceSpaces method to IntegrationService and using it here, similar to how getJiraProjects is used in JiraProjectSelector.

app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx (1)

9-13: Define a proper interface for Confluence config.

Same type safety concern as with SlackConfigProps - using any loses compile-time type checking.

+interface ConfluenceConfig {
+    connection_id?: string;
+    cloud_id?: string;
+    space_key?: string | null;
+    space_name?: string | null;
+    title?: string;
+    content?: string;
+    parent_page_id?: string;
+}
+
 interface ConfluenceConfigProps {
-    config: any;
-    onConfigChange: (config: any) => void;
+    config: ConfluenceConfig;
+    onConfigChange: (config: ConfluenceConfig) => void;
     readOnly?: boolean;
 }
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx (2)

168-173: Simplify the pluralization logic.

SonarCloud flags the negated condition. The expression can be simplified for readability.

 <p className="text-xs text-gray-500">
-    {projects.length} project{projects.length !== 1 ? "s" : ""}{" "}
-    found
+    {projects.length} {projects.length === 1 ? "project" : "projects"} found
 </p>

29-34: Use FC type annotation for consistency with coding guidelines.

Per the coding guidelines, functional components should use TypeScript FC types.

+import { FC } from "react";
+
-export const JiraProjectSelector = ({
+export const JiraProjectSelector: FC<JiraProjectSelectorProps> = ({
     integrationId,
     selectedProjectKey,
     onProjectChange,
     readOnly = false,
-}: JiraProjectSelectorProps) => {
+}) => {
app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx (1)

9-14: Remove unused workflow prop or use it.

The workflow prop is declared in the interface but never used in the component. Either remove it from the props interface or utilize it if needed.

 interface ConfluenceAgentConfigProps {
     config: any;
     onConfigChange: (config: any) => void;
     readOnly?: boolean;
-    workflow?: any;
 }
services/IntegrationService.ts (1)

272-297: Consider adding a typed response interface for getJiraProjects.

The method follows the established pattern in this service, but returns Promise<any>. For better type safety and developer experience, consider defining an interface for the Jira projects response.

interface JiraProjectsResponse {
  projects: Array<{
    id: string;
    key: string;
    name: string;
    // other fields as needed
  }>;
  total: number;
  // pagination fields
}

Then update the return type:

-  ): Promise<any> {
+  ): Promise<JiraProjectsResponse> {
app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx (2)

35-83: Webhook check triggers on every config change due to broad dependencies.

The useEffect depends on config.integrationId, config.integration_id, and config.cloud_id. If any of these change, the webhook check re-runs. This is correct for integration changes, but cloud_id is set alongside integrationId in the same update, potentially causing unnecessary duplicate API calls.

Consider using a single canonical identifier:

     }, [config.integrationId, config.integration_id, config.cloud_id]);
+    // Note: cloud_id dependency may cause duplicate calls when integration changes
+    // Consider using only integrationId once config shape is normalized

Alternatively, normalize the config shape upstream to use a single integrationId field.


117-173: Extract webhook status rendering into a helper component or variable.

The nested ternary operations for webhook status (checking → not configured → configured) reduce readability. Extract into a helper function or separate component.

const WebhookStatus = () => {
    if (checkingWebhook) {
        return (
            <div className="p-3 border border-blue-200 bg-blue-50 rounded-md flex items-start gap-2">
                <Info className="h-4 w-4 text-blue-600 mt-0.5" />
                <p className="text-sm text-blue-800">Checking webhook configuration...</p>
            </div>
        );
    }
    if (hasWebhook === false) {
        return (/* ... not configured UI ... */);
    }
    if (hasWebhook === true) {
        return (/* ... configured UI ... */);
    }
    return null;
};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdf689a and 3d3071d.

📒 Files selected for processing (20)
  • app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx (2 hunks)
  • app/(main)/workflows/components/editor/hooks/useWorkflowEditor.ts (1 hunks)
  • app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/agents/agent.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/color_utils.ts (3 hunks)
  • app/(main)/workflows/components/editor/nodes/index.ts (1 hunks)
  • app/(main)/workflows/components/editor/nodes/node-registry.ts (4 hunks)
  • app/(main)/workflows/components/editor/nodes/node.tsx (4 hunks)
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx (1 hunks)
  • app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx (2 hunks)
  • app/(main)/workflows/page.tsx (4 hunks)
  • services/AgentService.ts (1 hunks)
  • services/IntegrationService.ts (4 hunks)
  • services/WorkflowService.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use PascalCase for component names and camelCase for utility names
Order imports: React/Next imports first, then components, then utilities
Use Next.js error boundaries, optional chaining, and nullish coalescing for error handling

Files:

  • app/(main)/workflows/components/editor/hooks/useWorkflowEditor.ts
  • app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx
  • services/IntegrationService.ts
  • app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx
  • services/WorkflowService.ts
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx
  • app/(main)/workflows/components/editor/nodes/index.ts
  • app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx
  • app/(main)/workflows/components/editor/nodes/agents/agent.tsx
  • app/(main)/workflows/components/editor/nodes/color_utils.ts
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx
  • services/AgentService.ts
  • app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx
  • app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx
  • app/(main)/workflows/components/editor/nodes/node.tsx
  • app/(main)/workflows/page.tsx
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx
  • app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx
  • app/(main)/workflows/components/editor/nodes/node-registry.ts
**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.tsx: Use Tailwind CSS for styling and the cn utility for conditional classes
Use functional components with TypeScript FC types
Prefer destructuring props at the component level
Use the "use client" directive for client components

Files:

  • app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx
  • app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx
  • app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx
  • app/(main)/workflows/components/editor/nodes/agents/agent.tsx
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx
  • app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx
  • app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx
  • app/(main)/workflows/components/editor/nodes/node.tsx
  • app/(main)/workflows/page.tsx
  • app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx
  • app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx
  • app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx
🧬 Code graph analysis (9)
app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx (1)
services/AgentService.ts (1)
  • AgentService (6-243)
services/IntegrationService.ts (1)
lib/utils.ts (1)
  • parseApiError (195-297)
app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx (2)
app/(main)/workflows/components/editor/nodes/index.ts (1)
  • JiraTriggerNode (4-4)
app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx (1)
  • JiraTriggerNode (229-267)
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx (2)
services/IntegrationService.ts (2)
  • ConnectedIntegration (47-73)
  • IntegrationService (75-356)
lib/utils.ts (1)
  • cn (4-6)
app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx (8)
app/(main)/workflows/components/editor/nodes/index.ts (3)
  • JiraTriggerConfigComponent (24-24)
  • jiraTriggerNodeMetadata (13-13)
  • JiraTriggerNode (4-4)
services/IntegrationService.ts (1)
  • IntegrationService (75-356)
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx (1)
  • JiraIntegrationSelector (38-290)
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx (1)
  • JiraProjectSelector (29-187)
app/(main)/workflows/components/editor/nodes/node-registry.ts (1)
  • jiraTriggerNodeMetadata (95-95)
services/WorkflowService.ts (1)
  • WorkflowNode (103-110)
app/(main)/workflows/components/editor/nodes/color_utils.ts (1)
  • getNodeColors (17-74)
app/(main)/workflows/components/editor/handles.tsx (1)
  • SourceHandle (7-36)
app/(main)/workflows/components/editor/nodes/agents/agent.tsx (1)
app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx (1)
  • useAgentData (89-95)
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx (2)
services/IntegrationService.ts (1)
  • IntegrationService (75-356)
components/ui/select.tsx (5)
  • Select (150-150)
  • SelectTrigger (153-153)
  • SelectValue (152-152)
  • SelectContent (154-154)
  • SelectItem (156-156)
app/(main)/workflows/page.tsx (1)
services/AgentService.ts (1)
  • AgentService (6-243)
app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx (1)
services/IntegrationService.ts (2)
  • ConnectedIntegration (47-73)
  • IntegrationService (75-356)
🪛 GitHub Check: SonarCloud Code Analysis
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx

[warning] 107-112: Use , , , , , , or instead of the "combobox" role to ensure accessibility across all devices. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY3JPn89tq2rOV51&open=AZrfeY3JPn89tq2rOV51&pullRequest=237 [warning] 81-81: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY3JPn89tq2rOV5z&open=AZrfeY3JPn89tq2rOV5z&pullRequest=237 [warning] 26-29: Mark the props of the component as read-only. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY3JPn89tq2rOV5y&open=AZrfeY3JPn89tq2rOV5y&pullRequest=237 app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx [warning] 7-7: Remove this unused import of 'Input'. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6J&open=AZrfeY7HPn89tq2rOV6J&pullRequest=237 [warning] 12-12: 'lucide-react' imported multiple times. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6K&open=AZrfeY7HPn89tq2rOV6K&pullRequest=237 [warning] 142-142: Ambiguous spacing before next element code See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6M&open=AZrfeY7HPn89tq2rOV6M&pullRequest=237 [warning] 127-171: Extract this nested ternary operation into an independent statement. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6L&open=AZrfeY7HPn89tq2rOV6L&pullRequest=237 [warning] 164-171: Extract this nested ternary operation into an independent statement. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6O&open=AZrfeY7HPn89tq2rOV6O&pullRequest=237 [warning] 3-3: 'lucide-react' imported multiple times. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY7HPn89tq2rOV6I&open=AZrfeY7HPn89tq2rOV6I&pullRequest=237 app/(main)/workflows/components/editor/nodes/color_utils.ts [warning] 55-60: This case's code block is the same as the block for the case on line 37. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY8kPn89tq2rOV6V&open=AZrfeY8kPn89tq2rOV6V&pullRequest=237 app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx [warning] 171-171: Unexpected negated condition. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY67Pn89tq2rOV6H&open=AZrfeY67Pn89tq2rOV6H&pullRequest=237 app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx [warning] 21-21: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6QPn89tq2rOV59&open=AZrfeY6QPn89tq2rOV59&pullRequest=237 [warning] 53-53: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6QPn89tq2rOV5_&open=AZrfeY6QPn89tq2rOV5_&pullRequest=237 [warning] 37-37: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6QPn89tq2rOV5-&open=AZrfeY6QPn89tq2rOV5-&pullRequest=237 app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx [warning] 13-13: 'workflow' PropType is defined but prop is never used See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY76Pn89tq2rOV6Q&open=AZrfeY76Pn89tq2rOV6Q&pullRequest=237 [warning] 24-24: The empty object is useless. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY76Pn89tq2rOV6R&open=AZrfeY76Pn89tq2rOV6R&pullRequest=237 [warning] 83-83: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY76Pn89tq2rOV6S&open=AZrfeY76Pn89tq2rOV6S&pullRequest=237 app/(main)/workflows/page.tsx [warning] 302-302: agentTypes should be a Set, and use agentTypes.has() to check existence or non-existence. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY_9Pn89tq2rOV6X&open=AZrfeY_9Pn89tq2rOV6X&pullRequest=237 app/(main)/workflows/components/editor/nodes/triggers/jira/JiraIntegrationSelector.tsx [warning] 166-193: Extract this nested ternary operation into an independent statement. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6pPn89tq2rOV6G&open=AZrfeY6pPn89tq2rOV6G&pullRequest=237 app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx [warning] 34-38: Mark the props of the component as read-only. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV52&open=AZrfeY6CPn89tq2rOV52&pullRequest=237 [warning] 146-151: Use , , , , , , or instead of the "combobox" role to ensure accessibility across all devices. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV58&open=AZrfeY6CPn89tq2rOV58&pullRequest=237 [warning] 106-106: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV54&open=AZrfeY6CPn89tq2rOV54&pullRequest=237 [warning] 93-93: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV53&open=AZrfeY6CPn89tq2rOV53&pullRequest=237 [warning] 131-131: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV56&open=AZrfeY6CPn89tq2rOV56&pullRequest=237 [warning] 143-143: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6CPn89tq2rOV57&open=AZrfeY6CPn89tq2rOV57&pullRequest=237 app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx [warning] 73-73: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6cPn89tq2rOV6B&open=AZrfeY6cPn89tq2rOV6B&pullRequest=237 [warning] 57-57: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6cPn89tq2rOV6A&open=AZrfeY6cPn89tq2rOV6A&pullRequest=237 [warning] 88-88: A form label must be associated with a control. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY6cPn89tq2rOV6C&open=AZrfeY6cPn89tq2rOV6C&pullRequest=237 app/(main)/workflows/components/editor/nodes/node-registry.ts [warning] 101-101: Use export…from to re-export confluenceAgentNodeMetadata. See more on https://sonarcloud.io/project/issues?id=getmomentum_potpie-ui&issues=AZrfeY8QPn89tq2rOV6U&open=AZrfeY8QPn89tq2rOV6U&pullRequest=237 🔇 Additional comments (30) app/(main)/workflows/components/editor/nodes/agents/agent.tsx (1) 36-47: LGTM! Filtering logic is clear and well-implemented. The rename to allAgents and the inline filtering of workflow and system agents improves code clarity. The comments clearly explain the distinction between system agents and custom agents. services/WorkflowService.ts (1) 87-98: LGTM! The new NodeType values for Jira trigger, Confluence agent, and Slack/Confluence actions are correctly added and align with the PR's integration goals. services/AgentService.ts (2) 24-28: LGTM! The new includeWorkflowAgents parameter is well-designed with a default value of false, maintaining backward compatibility with existing callers. 40-45: Verify whether both list_system_agents and include_workflow_agents params are required. Both query parameters are set to the same includeWorkflowAgents value. Confirm this is intentional for API compatibility, or if one is redundant. app/(main)/workflows/page.tsx (4) 166-215: LGTM! The new workflow template is well-structured with proper node definitions, positions, and adjacency list. The template demonstrates the new Confluence documentation agent and Slack notification action working together. 247-252: LGTM! The agent fetch correctly includes workflow agents by passing true for the new includeWorkflowAgents parameter. The debug log will help trace agent loading issues. 311-318: LGTM! The systemAgentNames mapping provides clean human-readable names for system workflow agents, with appropriate fallback logic for custom agents. 570-574: LGTM! Minor formatting change to the status indicator className. The conditional logic for the animated pulse on active workflows is correct. app/(main)/workflows/components/editor/contexts/AgentDataContext.tsx (2) 15-16: LGTM! The new optional fields is_workflow_agent and requires_repo_context extend the Agent interface appropriately to support workflow-specific agent metadata. 45-54: LGTM! The fetch logic correctly retrieves all agents including workflow agents and maps the required fields. The mapping is explicit and type-safe. app/(main)/workflows/components/editor/nodes/triggers/trigger.tsx (2) 26-26: LGTM! Import follows the established pattern for trigger components. 69-70: LGTM! The Jira trigger case follows the same pattern as LinearTriggerNode, passing the data prop directly without explicit type assertion. This is consistent with the existing codebase. app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx (1) 152-179: LGTM! The command list rendering with selection state, check icon visibility, and the search value composition for filtering are well implemented. app/(main)/workflows/components/editor/nodes/color_utils.ts (2) 37-42: Duplicate color palettes for Jira and Confluence are acceptable. Static analysis flags identical code blocks, but this is intentional since both are Atlassian products sharing brand colors. Keeping them separate maintains clarity and allows independent customization if branding needs diverge. Also applies to: 55-60 61-66: LGTM! Slack purple palette is correctly defined with appropriate contrast. app/(main)/workflows/components/editor/nodes/node.tsx (2) 4-10: LGTM! New node component imports are properly organized and follow the existing import pattern. 22-23: LGTM! New trigger and agent type cases are correctly integrated into the existing switch patterns. Also applies to: 32-33 app/(main)/workflows/components/editor/nodes/index.ts (2) 13-18: LGTM! New metadata and config component exports are properly organized and follow the existing export pattern. Also applies to: 24-27 4-9: Missing ConfluenceAgentNode export. ConfluenceAgentNode is imported in node.tsx but not exported from this index file. If this component should be accessible from other parts of the codebase, add the export. app/(main)/workflows/components/editor/nodes/node-registry.ts (2) 9-21: LGTM! New node types are properly added to the NodeType union, extending the type system correctly for Jira triggers, Confluence actions, Slack messaging, and Confluence agent. 76-84: LGTM! New node metadata entries are correctly added to the availableNodes registry array. app/(main)/workflows/components/editor/nodes/actions/slack-send-message.tsx (1) 81-113: LGTM! The SlackSendMessageNode component is well-structured with proper color theming, conditional rendering for channel display, and appropriate handles for the workflow diagram. app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx (2) 72-76: Auto-selecting a space may trigger unexpected side effects. Automatically calling onSpaceChange when only one space exists might cause unexpected behavior if the parent component isn't prepared for an immediate callback during initial render. This could lead to state update warnings or re-render loops. Verify that the parent component (ConfluenceConfigComponent) handles this callback correctly during initial mount, and consider whether this auto-select should be opt-in via a prop. 141-201: LGTM on the popover implementation. The space selector UI with search functionality, selected state display, and proper conditional rendering is well-implemented. app/(main)/workflows/components/editor/nodes/actions/confluence-create-page.tsx (1) 117-173: LGTM on the node rendering component. The ConfluenceCreatePageNode component effectively displays integration status, space, and title with proper conditional rendering and visual indicators. app/(main)/workflows/components/editor/nodes/triggers/jira/JiraProjectSelector.tsx (2) 40-70: LGTM on the data fetching logic. The useEffect properly handles the loading state, error handling, and dependency array. Using IntegrationService.getJiraProjects maintains consistency with the service layer pattern. 121-128: Good use of sentinel value for "All projects" option. The __none__ sentinel pattern is a clean way to handle the "All projects" option in the Select component, which doesn't allow empty string values. app/(main)/workflows/components/editor/nodes/agents/confluence-agent.tsx (1) 112-172: LGTM! The ConfluenceAgentNode component is well-structured with proper conditional rendering, truncation for long text, and appropriate use of handles for the workflow editor graph. services/IntegrationService.ts (1) 32-37: LGTM on metadata extension. The addition of the webhooks array and index signature to the metadata interfaces properly supports the new Jira/Confluence integration workflows. The structure is consistent between ConnectedIntegrationResponse and ConnectedIntegration. Also applies to: 62-72 app/(main)/workflows/components/editor/nodes/triggers/jira/jira-trigger.tsx (1) 229-266: LGTM on the JiraTriggerNode component. The node component correctly handles both camelCase and snake_case property names for backward compatibility, uses appropriate styling from getNodeColors, and renders the connection handle properly.

@@ -0,0 +1,187 @@
import React, { useEffect, useState } from 'react';

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.

🛠️ Refactor suggestion | 🟠 Major

Missing "use client" directive.

This file uses React hooks (useState, useEffect) and browser APIs (useRouter), making it a client component. As per coding guidelines, add the directive at the top.

+"use client";
+
 import React, { useEffect, useState } from 'react';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import React, { useEffect, useState } from 'react';
"use client";
import React, { useEffect, useState } from 'react';
🤖 Prompt for AI Agents
In
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx
around lines 1 to 1, this file uses React hooks and browser APIs but is missing
the "use client" directive; add the line "use client" as the very first line of
the file (before any imports) so Next.js treats it as a client component, and
verify there are no server-only imports remaining.

Comment on lines +36 to +38
useEffect(() => {
loadIntegrations();
}, []);

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.

⚠️ Potential issue | 🟡 Minor

Missing dependencies in useEffect.

The useEffect that calls loadIntegrations references selectedIntegrationId and onIntegrationChange inside loadIntegrations, but these aren't in the dependency array. This could cause stale closure issues with the auto-select logic.

Consider wrapping loadIntegrations with useCallback or adding the dependencies:

+import React, { useEffect, useState, useCallback } from 'react';
+
+// Then wrap loadIntegrations:
+const loadIntegrations = useCallback(async () => {
+    // ... existing logic
+}, [selectedIntegrationId, onIntegrationChange]);
+
 useEffect(() => {
     loadIntegrations();
-}, []);
+}, [loadIntegrations]);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceIntegrationSelector.tsx
around lines 36 to 38, the useEffect calls loadIntegrations but omits
dependencies used inside loadIntegrations (selectedIntegrationId and
onIntegrationChange), which can lead to stale closures; fix by either wrapping
loadIntegrations in useCallback with selectedIntegrationId and
onIntegrationChange (and any other used values) in its dependency array and then
keeping useEffect dependent only on that memoized function, or by including
selectedIntegrationId and onIntegrationChange directly in the useEffect
dependency array so the effect reruns when they change.

Comment on lines +44 to +51
useEffect(() => {
if (integrationId) {
loadSpaces();
} else {
setSpaces([]);
setError(null);
}
}, [integrationId]);

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.

⚠️ Potential issue | 🟡 Minor

Add loadSpaces to useEffect dependencies or use useCallback.

The loadSpaces function is defined outside the effect but called within it, creating a dependency that React's exhaustive-deps rule would flag. This can cause stale closure issues.

+    const loadSpaces = useCallback(async () => {
+        // ... existing implementation
+    }, [integrationId, selectedSpaceKey, onSpaceChange]);
+
     useEffect(() => {
         if (integrationId) {
             loadSpaces();
         } else {
             setSpaces([]);
             setError(null);
         }
-    }, [integrationId]);
+    }, [integrationId, loadSpaces]);

Alternatively, move loadSpaces inside the useEffect if it's only used there.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
app/(main)/workflows/components/editor/nodes/actions/confluence/ConfluenceSpaceSelector.tsx
around lines 44 to 51, the useEffect calls loadSpaces but doesn't include it in
the dependency array which can cause stale closures; fix by either (A) wrapping
loadSpaces in useCallback with the correct dependencies (e.g., integrationId and
any other values it uses) and then add that memoized loadSpaces to the useEffect
dependency array, or (B) move the loadSpaces function body inside the useEffect
so it uses current values and keep [integrationId] as the dependency; pick one
approach and update related imports/types if needed.

Comment on lines +78 to +125
useEffect(() => {
if ((!integrationsLoaded && integrations.length === 0) || refreshKey > 0) {
setLoading(true);

IntegrationService.getConnectedIntegrations()
.then((allIntegrations) => {
// Filter for Jira integrations only
const jiraIntegrations = allIntegrations.filter(
(integration) => integration.type === "jira"
);
setIntegrations(jiraIntegrations);
setLoading(false);
setIntegrationsLoaded(true);
})
.catch((error) => {
console.error("Failed to load Jira integrations:", error);
setLoading(false);
setIntegrationsLoaded(true);
});
}
}, [integrationsLoaded, integrations.length, refreshKey]);

// Load integrations immediately if we have a selectedIntegrationId but no integrations loaded yet
useEffect(() => {
if (
selectedIntegrationId &&
!integrationsLoaded &&
integrations.length === 0
) {
setLoading(true);

IntegrationService.getConnectedIntegrations()
.then((allIntegrations) => {
// Filter for Jira integrations only
const jiraIntegrations = allIntegrations.filter(
(integration) => integration.type === "jira"
);
setIntegrations(jiraIntegrations);
setLoading(false);
setIntegrationsLoaded(true);
})
.catch((error) => {
console.error("Failed to load Jira integrations:", error);
setLoading(false);
setIntegrationsLoaded(true);
});
}
}, [selectedIntegrationId, integrationsLoaded, integrations.length]);

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.

🛠️ Refactor suggestion | 🟠 Major

Consolidate duplicate useEffect logic.

Both useEffect hooks (lines 78-98 and 101-125) contain identical data fetching logic. This violates DRY and can lead to race conditions or redundant API calls.

Consider extracting the fetch logic and consolidating into a single effect:

+    const loadIntegrations = useCallback(() => {
+        setLoading(true);
+        IntegrationService.getConnectedIntegrations()
+            .then((allIntegrations) => {
+                const jiraIntegrations = allIntegrations.filter(
+                    (integration) => integration.type === "jira"
+                );
+                setIntegrations(jiraIntegrations);
+                setLoading(false);
+                setIntegrationsLoaded(true);
+            })
+            .catch((error) => {
+                console.error("Failed to load Jira integrations:", error);
+                setLoading(false);
+                setIntegrationsLoaded(true);
+            });
+    }, []);
+
     useEffect(() => {
-        if ((!integrationsLoaded && integrations.length === 0) || refreshKey > 0) {
-            setLoading(true);
-
-            IntegrationService.getConnectedIntegrations()
-                .then((allIntegrations) => {
-                    // Filter for Jira integrations only
-                    const jiraIntegrations = allIntegrations.filter(
-                        (integration) => integration.type === "jira"
-                    );
-                    setIntegrations(jiraIntegrations);
-                    setLoading(false);
-                    setIntegrationsLoaded(true);
-                })
-                .catch((error) => {
-                    console.error("Failed to load Jira integrations:", error);
-                    setLoading(false);
-                    setIntegrationsLoaded(true);
-                });
+        if (!integrationsLoaded || refreshKey > 0) {
+            loadIntegrations();
         }
-    }, [integrationsLoaded, integrations.length, refreshKey]);
-
-    // Load integrations immediately if we have a selectedIntegrationId but no integrations loaded yet
-    useEffect(() => {
-        if (
-            selectedIntegrationId &&
-            !integrationsLoaded &&
-            integrations.length === 0
-        ) {
-            // ... duplicate code removed
-        }
-    }, [selectedIntegrationId, integrationsLoaded, integrations.length]);
+    }, [integrationsLoaded, refreshKey, loadIntegrations]);

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +100 to +101
export type NodeGroup = "github" | "linear" | "sentry" | "default" | "jira" | "confluence" | "slack";
export type NodeCategory = "trigger" | "agent" | "flow_control" | "manual_step" | "action";

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.

⚠️ Potential issue | 🟡 Minor

NodeGroup is missing "flow_control" compared to other definitions.

The NodeGroup type here differs from the definitions in color_utils.ts and node-registry.ts, which include "flow_control". This inconsistency could cause type errors when flow control nodes are used.

-export type NodeGroup = "github" | "linear" | "sentry" | "default" | "jira" | "confluence" | "slack";
+export type NodeGroup = "github" | "linear" | "sentry" | "default" | "jira" | "confluence" | "slack" | "flow_control";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export type NodeGroup = "github" | "linear" | "sentry" | "default" | "jira" | "confluence" | "slack";
export type NodeCategory = "trigger" | "agent" | "flow_control" | "manual_step" | "action";
export type NodeGroup = "github" | "linear" | "sentry" | "default" | "jira" | "confluence" | "slack" | "flow_control";
export type NodeCategory = "trigger" | "agent" | "flow_control" | "manual_step" | "action";
🤖 Prompt for AI Agents
In services/WorkflowService.ts around lines 100-101, the NodeGroup union is
missing the "flow_control" member which causes divergence from color_utils.ts
and node-registry.ts; update the NodeGroup type to include "flow_control" so it
matches the other definitions and avoids type errors when flow control nodes are
used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant