Skip to content

feat(ui): add new scan jobs view#11258

Open
alejandrobailo wants to merge 27 commits into
masterfrom
feat/PROWLER-1761-new-scans-view
Open

feat(ui): add new scan jobs view#11258
alejandrobailo wants to merge 27 commits into
masterfrom
feat/PROWLER-1761-new-scans-view

Conversation

@alejandrobailo
Copy link
Copy Markdown
Contributor

@alejandrobailo alejandrobailo commented May 20, 2026

Context

Adds the new Scan Jobs UI flow for PROWLER-1761. The page introduces tabbed scan job views while keeping backend-dependent functionality constrained to what is currently available in the OSS API.

Description

  • Add the new Scan Jobs page shell with Active, Completed, Scheduled, and Imported tabs.
  • Add the Launch Scan modal and scan job table states using shadcn UI components.
  • Add scan table utilities for tab filtering, labels, durations, and safe tab fallback behavior.
  • Render Completed scan findings as the existing View Findings link instead of fail/pass counters until backend returns those counters.
  • Gate Cloud-only scan actions in OSS:
    • Imported Scans is disabled outside Prowler Cloud and falls back to Active Scans when reached by URL.
    • Import Findings is disabled outside Prowler Cloud and shows the standard Available in Prowler Cloud badge.
    • Edit Scan Schedule remains disabled and shows the standard Cloud tooltip outside Prowler Cloud.
  • Hide Cancel Scan for now with a TODO until backend exposes a public scan cancellation endpoint.
  • Add TODOs for backend-owned values, including the Scheduled tab Last Scan value, which should represent the latest completed scan for the provider.
  • Update scan E2E page object/documentation and keep focused unit coverage while removing low-value source-string tests.

Steps to review

  1. Open /scans and verify the Scan Jobs page renders with the expected tabs.
  2. Check that filters and actions are aligned together on the left, with Import Findings and Launch Scan matching the Findings Create Alert button size.
  3. Click Launch Scan, select a connected cloud account, optionally enter a scan note, and launch the scan.
  4. Verify active scans refresh while queued/executing scans are visible.
  5. Check Completed and Scheduled tabs render their tab-specific columns.
  6. In OSS mode, verify Imported Scans is disabled with a Cloud tooltip and Import Findings is disabled with the Cloud badge.
  7. Verify Cancel Scan is not shown until backend cancellation support exists.
  8. Review unit coverage around scan table utilities, scan job columns, row actions, page shell, launch scan form payload, and auto-refresh behavior.

Validation run locally:

cd ui
pnpm test:unit scan-jobs-columns
pnpm test:unit scan-jobs-row-actions
pnpm test:unit scans-page-shell
pnpm test:unit scans-table.utils scan-jobs-row-actions scans-page-shell
pnpm test:unit scan-jobs-columns.test.tsx scan-jobs-table.test.tsx scans-table.utils.test.ts launch-scan-modal.test.tsx
pnpm run typecheck
pnpm run lint:check
pnpm exec prettier --check app/'(prowler)'/scans/page.tsx components/scans/scans-page-shell.tsx components/scans/scans-page-shell.test.tsx components/scans/scans-table.utils.ts components/scans/scans-table.utils.test.ts components/scans/table/scans/scan-jobs-row-actions.tsx components/scans/table/scans/scan-jobs-row-actions.test.tsx components/scans/table/scans/scan-jobs-columns.tsx components/scans/table/scans/scan-jobs-columns.test.tsx tests/scans/scans.md

E2E not run locally because it requires real AWS E2E credentials.

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me, if not, request it via the issue/feature in here or Prowler Community Slack

SDK/CLI

  • Are there new checks included in this PR? No
    • If so, do we need to update permissions for the provider? No

UI

  • All issue/task requirements work as expected on the UI
  • If this PR adds or updates npm dependencies, include package-health evidence (maintenance, popularity, known vulnerabilities, license, release age) and explain why existing/native alternatives are insufficient. No new npm dependencies added.
  • Screenshots/Video of the functionality flow (if applicable) - Mobile (X < 640px)
  • Screenshots/Video of the functionality flow (if applicable) - Table (640px > X < 1024px)
  • Screenshots/Video of the functionality flow (if applicable) - Desktop (X > 1024px)
  • Ensure new entries are added to CHANGELOG.md, if applicable.

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 new entries are added to CHANGELOG.md, if applicable.

License

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

✅ All necessary CHANGELOG.md files have been updated.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🔒 Container Security Scan

Image: prowler-ui:ede7be1
Last scan: 2026-05-22 12:55:05 UTC

📊 Vulnerability Summary

Severity Count
🔴 Critical 2
Total 2

2 package(s) affected

⚠️ Action Required

Critical severity vulnerabilities detected. These should be addressed before merging:

  • Review the detailed scan results
  • Update affected packages to patched versions
  • Consider using a different base image if updates are unavailable

📋 Resources:

@alejandrobailo alejandrobailo self-assigned this May 20, 2026
@alejandrobailo alejandrobailo marked this pull request as ready for review May 20, 2026 14:51
@alejandrobailo alejandrobailo requested a review from a team as a code owner May 20, 2026 14:52
alejandrobailo and others added 12 commits May 20, 2026 16:54
Drops the legacy scans table chain and its supporting forms after the
new scans view replaced them. Nothing in the active render tree
referenced these files anymore — `ScansLaunchSection`, `LaunchScanWorkflow`,
`ScansTableWithPolling`, `ColumnGetScans` and the rest were only kept
alive by their own internal cross-references.

Removes:
- `components/scans/forms/` (edit-scan-form, schedule-form)
- `components/scans/launch-workflow/` (launch-scan-workflow-form, select-scan-provider)
- `components/scans/scans-launch-section.{tsx,test.tsx}`
- `components/scans/table/scans/{column-get-scans,data-table-row-actions,data-table-row-details,scans-table-with-polling,skeleton-scan-detail}.tsx`
- `editScanFormSchema` from `types/formSchemas.ts` (only used by the deleted form)

The `table/scans/index.ts` barrel is trimmed to the surviving entries
(scan-jobs-columns, scan-jobs-row-actions, scan-jobs-table).
Introduces `EditAliasModal`, a shadcn-based modal mirroring the styling
and patterns of `LaunchScanModal` (Modal/Field/FieldLabel/Input,
inline useState validation, toast() function). It reuses the existing
`updateScan` server action which PATCHes the scan's `name` attribute.

`ScanJobsRowActions` collapses the previous "Edit Alias" + disabled
"Edit Scan Schedule" pair into a single "Edit" item that opens the
alias modal. The schedule edit will be re-added to the same modal once
the backend exposes a schedule update endpoint — a TODO comment marks
the expansion point.
Drops the redundant "Scan" prefix from labels in the scans view since
the user is already inside that context:

- Column titles in `scan-jobs-columns.tsx`: "Scan Time" → "Duration",
  "Scan Schedule" → "Schedule", "Scan Date" → "Completed",
  "Next Scan" → "Next Run".
- Tab labels in `scans-table.utils.ts`: "Active Scans" → "Active",
  "Completed Scans" → "Completed", "Scheduled Scans" → "Scheduled".

Also adds the Alias column to the Scheduled tab for consistency with
Active and Completed — schedules without an alias still surface their
provider account in the first column.
When no rows in the table can expand, DataTableExpandAllToggle returned
null, leaving the header without the 16px slot that its expandable cells
still reserve via <div className="w-4" />. The result was a horizontal
offset between the header checkbox and the row checkboxes in tables like
Providers when a tenant has no organization rows.

Always render the 16px placeholder when the toggle has nothing to do,
mirroring the behaviour of the per-row DataTableExpandToggle. Header and
cells now agree on the same layout grid regardless of whether expansion
is currently available.
Adds backend-backed sorting to the columns whose value is listed in the
ScanViewSet ordering_fields and exists on the Scan model: Alias (name),
Schedule (trigger), Completed (updated_at) and Next Run (scheduled_at).
Sorting is wired via accessorFn so TanStack Table's getCanSort() returns
true and DataTableColumnHeader renders the sortable chevron button.

Extracts the previously inlined Schedule column into a shared
scanScheduleColumn constant — the three tabs were duplicating the same
definition. Launched (started_at) stays unsorted because the API does
not expose that field for ordering.

Also hides the Duration column behind a TODO comment. The backend
currently leaves attributes.duration empty for active scans, so the
column rendered blank and added more noise than value. Restoring it is
a one-line revert once the API populates the field.
Each tab in the scan jobs view exposes a different set of sortable
columns: Active sorts by Alias/Schedule, Scheduled adds Next Run,
Completed adds Completed. Carrying the sort URL param across tabs left
the table ordered by a field whose chevron indicator no longer existed
on screen, producing data ordered in a non-default way with nothing to
explain why.

Clear sort=... when setTab fires so each tab starts from its natural
default ordering. Other URL params (filters, etc.) keep their value
because they are orthogonal to the tab choice. Covered by a test that
seeds sort=trigger, clicks a different tab and asserts the resulting
URL has no sort param.
@pfe-nazaries pfe-nazaries self-requested a review May 22, 2026 08:08
pfe-nazaries
pfe-nazaries previously approved these changes May 22, 2026
},
});

describe("ScanJobsRowActions", () => {
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.

Missing test for open/download finding branches


import { ScanJobsRowActions } from "./scan-jobs-row-actions";

const { pushMock, toastMock } = vi.hoisted(() => ({
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.

These mocks are used below to mock real push and toast behaviour, but never asserted on text that they are being called as expected

icon={<Eye />}
label="View Findings"
onSelect={openFindings}
disabled={!scanDate}
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.

Align the disabled condition with the early return if inside openFindings function

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants