Skip to content

refactor(ui): centralize Jira dispatch flow#12092

Merged
alejandrobailo merged 5 commits into
masterfrom
refactor/jira-dispatch-cleanup
Jul 22, 2026
Merged

refactor(ui): centralize Jira dispatch flow#12092
alejandrobailo merged 5 commits into
masterfrom
refactor/jira-dispatch-cleanup

Conversation

@alejandrobailo

@alejandrobailo alejandrobailo commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Context

Follow-up to #12001. The grouped Jira dispatch UI worked through several independent entry points, but each one owned part of the Cloud gating, modal state, labels, dispatch modes, polling, and retry behavior. This made the flow harder to maintain and caused inconsistent behavior between the selection menu and row actions.

Description

  • centralize Jira gating, action copy, modal state, and modal rendering behind a shared action item and one global modal host
  • keep the Cloud-only message exclusively in the tooltip and route non-Cloud grouped actions to the existing upgrade modal
  • open the same Jira modal from finding-group row actions in Cloud deployments
  • reuse one dispatch executor for batch submission, task tracking, result aggregation, and safe failed-Finding retries
  • rename the floating mute component to reflect that it now hosts multiple selection actions
  • extract paginated Finding Group filter-option loading into a focused helper
  • replace source-coupled and duplicated tests with smaller behavior-focused coverage

No npm dependencies are added or updated. The existing ui/changelog.d/grouped-jira-dispatch-ui.added.md fragment from #12001 already covers this functionality.

Steps to review

  1. In a Cloud deployment, select Findings or a Finding Group and verify the selection action opens the Jira modal with the correct grouped/individual choice.
  2. Open a Finding Group row action and verify Send 1 Finding Group to Jira opens the same modal.
  3. In a non-Cloud deployment, hover a grouped Jira action and verify Available only in Prowler Cloud appears only in the tooltip; clicking it opens the upgrade modal.
  4. Verify a single Finding can still open Jira dispatch outside Cloud.
  5. Run:
    • cd ui && pnpm typecheck
    • cd ui && pnpm lint:check
    • cd ui && pnpm format:check
    • cd ui && pnpm test:unit

Local result: 342 test files and 2,243 tests passed.

Checklist

Community Checklist

SDK/CLI

  • Are there new checks included in this PR? No

UI

  • All issue/task requirements work as expected on the UI
  • If this PR adds or updates npm dependencies, include package-health evidence. (Not applicable: no dependency changes.)
  • Screenshots/Video of the functionality flow - Mobile. (Not applicable: no layout changes.)
  • Screenshots/Video of the functionality flow - Tablet. (Not applicable: no layout changes.)
  • Screenshots/Video of the functionality flow - Desktop. (Not applicable: no layout changes.)
  • Ensure a changelog fragment is added under ui/changelog.d/, if applicable. (Covered by the existing feat(ui): add Jira dispatch choices for finding selections #12001 fragment.)

API

  • All issue/task requirements work as expected on the API
  • Endpoint response output (if applicable)
  • EXPLAIN ANALYZE output for new/modified queries or indexes (if applicable)
  • Performance test results (if applicable)
  • Any other relevant evidence of the implementation (if applicable)
  • Verify if API specs need to be regenerated.
  • Check if version updates are required (e.g., specs, uv, etc.).
  • Ensure a changelog fragment is added under api/changelog.d/, if applicable.

MCP Server

  • All issue/task requirements work as expected on the MCP Server
  • Ensure a changelog fragment is added under mcp_server/changelog.d/, if applicable.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Summary by CodeRabbit

  • New Features

    • Streamlined “Send to Jira” actions across findings, groups, resources, and detail views via a shared dispatch flow.
    • Consistent action labels for finding groups vs findings, with unified grouped/individual dispatch behavior and upgrade guidance when needed.
    • Added centralized Jira dispatch execution with aggregate progress messaging and automatic retry for failures.
  • Bug Fixes

    • Muted findings remain hidden by default unless explicitly enabled.
    • Finding Group filter options now load reliably across all available pages.
    • Bulk selection mute flow properly resets from async “preparing” failures and re-enables after retry/prep errors.

@alejandrobailo
alejandrobailo requested a review from a team as a code owner July 22, 2026 13:20
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Changes detected in the following folders without a changelog fragment:

  • ui

A changelog fragment is a small Markdown file named <slug>.<type>.md under <component>/changelog.d/, where <type> is one of added, changed, deprecated, removed, fixed or security. Its content is the changelog entry text, without the PR link (added automatically at release time) and without a trailing period. For example:

echo 'Entry text describing the change' > <component>/changelog.d/jira-dispatch-cleanup.fixed.md

If this PR does not need a changelog entry, add the no-changelog label instead.

@alejandrobailo alejandrobailo added the no-changelog Skip including change in changelog/release notes label Jul 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

No Conflicts

No conflict markers, and the branch merges cleanly into its base.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR centralizes finding-group filter loading and refactors Jira dispatch around shared payloads, global state, reusable action components, batch execution, retry handling, and modal hosting. Findings tables, drawers, drill-downs, and selection actions now use the shared flow.

Changes

Jira dispatch and findings filtering

Layer / File(s) Summary
Shared finding-group filter options
ui/lib/finding-group-filter-options.ts, ui/app/(prowler)/findings/page.tsx
Finding-group option pagination, deduplication, and own-filter exclusion moved into a shared helper used by the findings page.
Dispatch contracts and action state
ui/types/jira-dispatch.ts, ui/store/jira-dispatch/*, ui/lib/jira-dispatch-action.ts, ui/lib/jira-dispatch-selection.ts
Added Jira payload types, Zustand state, payload construction, dispatch-mode calculations, upgrade gating, and action-label generation.
Batch execution and retry handling
ui/lib/jira-dispatch-execution.ts, ui/components/findings/send-to-jira-modal.tsx, ui/components/findings/jira-dispatch-task-handler.tsx
Centralized Jira batch sending, task tracking, result aggregation, warnings, errors, retry batches, and modal outcome handling.
Shared dispatch UI
ui/components/findings/jira-dispatch-*.tsx, ui/components/findings/floating-selection-actions.tsx
Added reusable Jira dropdown and modal-host components and routed floating selection actions through Jira payloads.
Findings action integration
ui/components/findings/table/*, ui/components/resources/table/resource-detail-content.tsx
Finding tables, drill-downs, row actions, drawers, and resource selections now build payloads and open the shared Jira dispatch flow.
Global modal wiring
ui/components/layout/main-layout/*
Mounted JiraDispatchModalHost in MainLayout and added coverage for its presence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FindingsSelection
  participant JiraDispatchActionItem
  participant useJiraDispatchStore
  participant JiraDispatchModalHost
  participant SendToJiraModal
  participant executeJiraDispatchBatches
  FindingsSelection->>JiraDispatchActionItem: provide Jira payload
  JiraDispatchActionItem->>useJiraDispatchStore: openJiraDispatch(payload)
  useJiraDispatchStore->>JiraDispatchModalHost: expose activePayload
  JiraDispatchModalHost->>SendToJiraModal: render payload and dispatch settings
  SendToJiraModal->>executeJiraDispatchBatches: execute selected batches
  executeJiraDispatchBatches-->>SendToJiraModal: aggregate success, warnings, errors, retry batch
Loading

Possibly related PRs

Suggested reviewers: hugopbrito

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: centralizing the Jira dispatch flow in the UI.
Description check ✅ Passed The description follows the template with Context, Description, Steps to review, and Checklist sections and includes the needed implementation notes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/jira-dispatch-cleanup

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.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🔒 Container Security Scan

Image: prowler-ui:949b94e
Last scan: 2026-07-22 15:31:02 UTC

✅ No Vulnerabilities Detected

The container image passed all security checks. No known CVEs were found.

📋 Resources:

@alejandrobailo alejandrobailo self-assigned this Jul 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ui/components/findings/table/data-table-row-actions.tsx (1)

154-159: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Duplicate selection-resolution logic between getDisplayIds and getJiraTargetIds.

Both functions have identical bodies (same condition, same fallback). Consolidate into a single computed value shared by mute and Jira dispatch paths to avoid future divergence.

♻️ Proposed consolidation
-  const getDisplayIds = (): string[] => {
-    if (isCurrentSelected && hasMultipleSelected) {
-      return selectedFindingIds;
-    }
-    return [muteKey];
-  };
+  const getDisplayIds = (): string[] =>
+    isCurrentSelected && hasMultipleSelected ? selectedFindingIds : [muteKey];
...
-  const getJiraTargetIds = (): string[] => {
-    if (isCurrentSelected && hasMultipleSelected) {
-      return selectedFindingIds;
-    }
-    return [muteKey];
-  };
-
-  const jiraTargetIds = getJiraTargetIds();
+  const jiraTargetIds = getDisplayIds();

Also applies to: 170-175

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/components/findings/table/data-table-row-actions.tsx` around lines 154 -
159, Consolidate the duplicate selection-resolution logic currently in
getDisplayIds and getJiraTargetIds into one shared computed value within the
row-actions component. Use that value for both mute and Jira dispatch paths,
preserving the existing selectedFindingIds condition and muteKey fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/components/findings/table/column-finding-resources.tsx`:
- Around line 84-95: Extract the repeated jiraSelection/jiraPayload construction
into a shared buildJiraDispatchPayload helper alongside
createJiraTargetSelection, preserving the JiraDispatchModalPayload fields and
optional-result behavior. Update column-finding-resources.tsx lines 84-95,
findings-group-drill-down.tsx lines 119-130, resource-detail-drawer-content.tsx
lines 415-423, and OtherFindingRow’s inline payload construction at lines
1571-1669 to call the helper, passing only the fields required by each context.

---

Outside diff comments:
In `@ui/components/findings/table/data-table-row-actions.tsx`:
- Around line 154-159: Consolidate the duplicate selection-resolution logic
currently in getDisplayIds and getJiraTargetIds into one shared computed value
within the row-actions component. Use that value for both mute and Jira dispatch
paths, preserving the existing selectedFindingIds condition and muteKey
fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7dc84965-db2d-4f6d-a54c-c7ee59154c53

📥 Commits

Reviewing files that changed from the base of the PR and between ff45f46 and 94314df.

📒 Files selected for processing (34)
  • ui/app/(prowler)/findings/page.test.ts
  • ui/app/(prowler)/findings/page.tsx
  • ui/components/findings/floating-selection-actions.test.tsx
  • ui/components/findings/floating-selection-actions.tsx
  • ui/components/findings/jira-dispatch-action-item.test.tsx
  • ui/components/findings/jira-dispatch-action-item.tsx
  • ui/components/findings/jira-dispatch-modal-host.test.tsx
  • ui/components/findings/jira-dispatch-modal-host.tsx
  • ui/components/findings/jira-dispatch-task-handler.test.tsx
  • ui/components/findings/jira-dispatch-task-handler.tsx
  • ui/components/findings/send-to-jira-modal.test.tsx
  • ui/components/findings/send-to-jira-modal.tsx
  • ui/components/findings/table/column-finding-resources.test.tsx
  • ui/components/findings/table/column-finding-resources.tsx
  • ui/components/findings/table/data-table-row-actions.test.tsx
  • ui/components/findings/table/data-table-row-actions.tsx
  • ui/components/findings/table/findings-group-drill-down.test.ts
  • ui/components/findings/table/findings-group-drill-down.tsx
  • ui/components/findings/table/findings-group-table.test.tsx
  • ui/components/findings/table/findings-group-table.tsx
  • ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx
  • ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx
  • ui/components/layout/main-layout/main-layout.test.tsx
  • ui/components/layout/main-layout/main-layout.tsx
  • ui/components/resources/table/resource-detail-content.tsx
  • ui/lib/finding-group-filter-options.test.ts
  • ui/lib/finding-group-filter-options.ts
  • ui/lib/jira-dispatch-action.test.ts
  • ui/lib/jira-dispatch-action.ts
  • ui/lib/jira-dispatch-execution.test.ts
  • ui/lib/jira-dispatch-execution.ts
  • ui/store/index.ts
  • ui/store/jira-dispatch/store.ts
  • ui/types/jira-dispatch.ts
💤 Files with no reviewable changes (2)
  • ui/components/findings/table/findings-group-drill-down.test.ts
  • ui/app/(prowler)/findings/page.test.ts

Comment thread ui/components/findings/table/column-finding-resources.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ui/components/findings/send-to-jira-modal.test.tsx (1)

33-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the ToastAction mock clickable.

The mock drops onClick, so tests cannot exercise the “Retry failed” path. Render the action as a button and assert that retry invokes executeJiraDispatchBatches with the retry batch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/components/findings/send-to-jira-modal.test.tsx` at line 33, Update the
ToastAction mock to render a clickable button that forwards its onClick handler,
then add or update the retry test to click “Retry failed” and assert
executeJiraDispatchBatches is called with the retry batch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/components/findings/send-to-jira-modal.test.tsx`:
- Around line 184-207: Update the “closes the modal before navigating to Jira
configuration” test around configureLink to mock or observe the navigation
target, then assert that onOpenChange(false) is recorded before navigation
occurs. Preserve the existing click flow and modal-closure assertion while
explicitly verifying the required ordering.

---

Outside diff comments:
In `@ui/components/findings/send-to-jira-modal.test.tsx`:
- Line 33: Update the ToastAction mock to render a clickable button that
forwards its onClick handler, then add or update the retry test to click “Retry
failed” and assert executeJiraDispatchBatches is called with the retry batch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 91f1339c-15ac-449a-b586-f7e878be42f7

📥 Commits

Reviewing files that changed from the base of the PR and between 94314df and b1ead9a.

📒 Files selected for processing (3)
  • ui/components/findings/send-to-jira-modal.test.tsx
  • ui/components/findings/send-to-jira-modal.tsx
  • ui/components/shadcn/custom/custom-banner.tsx

Comment thread ui/components/findings/send-to-jira-modal.test.tsx
@alejandrobailo

Copy link
Copy Markdown
Contributor Author

Addressed the two outside-diff CodeRabbit findings: 12d485174 reuses one target-ID value for mute and Jira actions; 12a3878d2 forwards ToastAction click props and covers retrying only the failed Jira batch.

@alejandrobailo

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/components/findings/send-to-jira-modal.test.tsx`:
- Around line 234-249: Update the test around executeJiraDispatchBatchesMock and
partialToast to wait until a toast titled "Partial success" with an action has
been emitted before extracting partialToast.action and rendering it. Keep the
existing executor-call assertion, rerender flow, and retry-action rendering
unchanged.

In `@ui/components/findings/table/data-table-row-actions.tsx`:
- Around line 165-176: Update selectedResourceCount in the
createJiraDispatchPayload call to use actionTargetIds.length when dispatching
multiple Finding Group selections, while preserving the current
finding.resourcesFail value for a single group and leaving non-group targets
undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6728f464-8d96-4e1d-8fd4-a7b85a2b4ec1

📥 Commits

Reviewing files that changed from the base of the PR and between b1ead9a and 12a3878.

📒 Files selected for processing (6)
  • ui/components/findings/send-to-jira-modal.test.tsx
  • ui/components/findings/table/column-finding-resources.tsx
  • ui/components/findings/table/data-table-row-actions.tsx
  • ui/components/findings/table/findings-group-drill-down.tsx
  • ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx
  • ui/lib/jira-dispatch-selection.ts

Comment thread ui/components/findings/send-to-jira-modal.test.tsx
Comment thread ui/components/findings/table/data-table-row-actions.tsx
@alejandrobailo
alejandrobailo merged commit dcf2736 into master Jul 22, 2026
42 checks passed
@alejandrobailo
alejandrobailo deleted the refactor/jira-dispatch-cleanup branch July 22, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ui no-changelog Skip including change in changelog/release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants