-
Notifications
You must be signed in to change notification settings - Fork 48
Add TaskProgress components and remove obsolete UI #1127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add TaskProgress components and remove obsolete UI #1127
Conversation
Reviewer's GuideThis PR modernizes the inventory upload UI by replacing the legacy ProgressOutput-based Dashboard with new PatternFly TaskProgress and TaskHistory components, integrates with ForemanTasks API via new controller endpoints, refactors the asynchronous upload job to remove obsolete ProgressOutput logic, and cleans up associated Redux, controller, and test code. Sequence diagram for fetching current and historical task datasequenceDiagram
actor User
participant UI as Dashboard UI
participant API as TasksController API
participant DB as ForemanTasks::Task
User->>UI: Open inventory upload dashboard
UI->>API: GET /api/v2/rh_cloud/inventory_upload/tasks/current
API->>DB: Query active ForemanTasks
DB-->>API: Return active tasks
API-->>UI: Return current tasks JSON
UI->>API: GET /api/v2/rh_cloud/inventory_upload/tasks/history
API->>DB: Query recent ForemanTasks
DB-->>API: Return historical tasks
API-->>UI: Return historical tasks JSON
UI-->>User: Render TaskProgress and TaskHistory components
Entity relationship diagram for Account and Task dataerDiagram
ACCOUNT ||--o{ TASK : has
ACCOUNT {
id string
generate_task_id string
upload_task_id string
report_file_paths string[]
}
TASK {
id string
label string
action string
state string
result string
progress number
started_at string
ended_at string
duration number
humanized string
}
Class diagram for new and updated UI componentsclassDiagram
class TaskProgress {
+task: Task
+title: string
+emptyMessage: string
+render()
}
class TaskHistory {
+tasks: Task[]
+title: string
+render()
}
class NavContainer {
+items: Array
+render()
}
class Dashboard {
+account: Account
+render()
}
class Task {
+id: string
+state: string
+result: string
+progress: number
+started_at: string
+ended_at: string
+duration: number
}
class Account {
+generate_task: Task
+upload_task: Task
+report_file_paths: string[]
+id: string
}
Dashboard --> NavContainer
NavContainer --> TaskProgress
NavContainer --> TaskHistory
Account --> Task
Class diagram for new TasksController API endpointsclassDiagram
class TasksController {
+current()
+history()
-task_json(task)
}
class ForemanTasks_Task {
+id: string
+label: string
+action: string
+state: string
+result: string
+progress: number
+started_at: string
+ended_at: string
+duration: number
+humanized: string
}
TasksController --> ForemanTasks_Task
Class diagram for refactored UploadReportDirectJobclassDiagram
class UploadReportDirectJob {
+plan(filename, organization_id)
+try_execute()
+upload_file(cer_path)
+move_to_done_folder()
+logger()
+rescue_strategy_for_self()
}
class DynflowAction
UploadReportDirectJob --|> DynflowAction
UploadReportDirectJob ..> logger
UploadReportDirectJob ..> move_to_done_folder
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- NavContainer is now using useSelector but doesn’t import it from react-redux—please add the missing import to avoid runtime errors.
- The history endpoint accepts a raw limit param; consider validating/sanitizing it (e.g. enforce a minimum of 1 and a reasonable maximum) to prevent unintended zero or unbounded queries.
- For better scalability, think about adding pagination metadata (total count, next page token, etc.) or stronger page controls to the tasks history API rather than returning only a simple limit-bound list.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- NavContainer is now using useSelector but doesn’t import it from react-redux—please add the missing import to avoid runtime errors.
- The history endpoint accepts a raw limit param; consider validating/sanitizing it (e.g. enforce a minimum of 1 and a reasonable maximum) to prevent unintended zero or unbounded queries.
- For better scalability, think about adding pagination metadata (total count, next page token, etc.) or stronger page controls to the tasks history API rather than returning only a simple limit-bound list.
## Individual Comments
### Comment 1
<location> `test/jobs/upload_report_direct_job_test.rb:229-232` </location>
<code_context>
action.send(:try_execute)
end
-
- # Verify progress output shows error
- label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
- output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
- assert_match(/Upload failed/, output)
end
</code_context>
<issue_to_address>
**suggestion (testing):** Removed assertions for progress output error reporting.
Please ensure tests verify that errors are properly captured in the updated task result and status fields, particularly for failed uploads and timeouts.
</issue_to_address>
### Comment 2
<location> `test/jobs/upload_report_direct_job_test.rb:314-317` </location>
<code_context>
# Verify file still exists (not moved or deleted)
assert File.exist?(test_file), "File should remain when upload is aborted"
-
- # Verify progress output mentions missing certificate
- label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
- output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
- assert_match(/Skipping organization.*no candlepin certificate/, output)
-
- # Verify status indicates abortion
</code_context>
<issue_to_address>
**suggestion (testing):** Removed test for progress output when certificate is missing.
Add a test to verify that missing certificates result in the correct task status or result, ensuring error handling is properly validated.
Suggested implementation:
```ruby
# Verify file still exists (not moved or deleted)
assert File.exist?(test_file), "File should remain when upload is aborted"
# Verify that missing certificates result in the correct task status or result
job = ForemanInventoryUpload::Async::UploadReportDirectJob.new
result = job.perform(@organization.id, test_file)
assert result.failed?, "Job should fail when certificate is missing"
assert_match(/no candlepin certificate/, result.error_message)
```
- If `ForemanInventoryUpload::Async::UploadReportDirectJob` does not return a result object with `failed?` and `error_message`, you may need to adjust the assertions to match the actual error reporting mechanism (e.g., checking a status field, exception, or log output).
- Ensure that the test setup triggers the missing certificate scenario (e.g., by stubbing or removing the certificate for the organization).
</issue_to_address>
### Comment 3
<location> `test/controllers/accounts_controller_test.rb:11-20` </location>
<code_context>
- generate_label = ForemanInventoryUpload::Async::GenerateReportJob.output_label(test_org.id)
</code_context>
<issue_to_address>
**suggestion (testing):** Test updated to verify new API response structure for account tasks.
Please add assertions for the state, result, and timestamps within 'generate_task' and 'upload_task' to fully validate the API response.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
28679a1 to
e0918b7
Compare
qcjames53
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Jeremy, nice job on this PR! The new inventory upload page seems to be really solid and /api/v2/rh_cloud/inventory_upload/tasks/current and /api/v2/rh_cloud/inventory_upload/tasks/history work great when testing manually. Big fan of how the current org is auto-populated in the search field. I have a few suggested changes / questions:
I'd prefer there to be a margin between the text and the settings window. Maybe put this text in an box clearly separated from the rest of form? I'm happy to chat about this but it seems odd to put this description front and center instead of the web form?

Are customers going to be okay with the output of the inventory status sync? Should this be a more permanent part of the page rather than a notification?

The three obfuscation settings remain enabled after toggling back to 'Analytics' from 'Minimal'. I love how minimal flips them on and disables the field. How hard would it be for them to retain their previous values when going back to Analytics though? I notice they maintain state through refresh so if this is too tricky I think it's fine to nix.

|
I was trying to find examples but the best I could come up with was the about page: table on the left and lots of text on the right. Could you implement something like that here? Or if not, could the text be limited to ~80ch? |
|
@qcjames53 Sorry, I should have been more clear that this redesign only affects the bottom half of the page - the Generate & Upload Report section. We do have mocks for a redesign of the top half (which look MUCH better than this) but that's coming at a later date. 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, thanks :) |
|
Hey @jeremylenz! I was thinking about this over the weekend and perhaps it would be better to fix all the foreman_rh_cloud controller authentication issues as a part of a separate bug fix? You didn't introduce any of these vulnerabilities so I don't think it should be on you to fix them. I'd still very much appreciate if you could add input validation though, if you don't mind. |
- Add input validation to TasksController and ReportsController - Validate organization_id parameter (type and existence) - Add bounds checking for limit parameter (1-100) - Use Foreman::Cast.to_bool for disconnected parameter - Return proper HTTP error codes (400, 404) - Replace obsolete GenerateReportJob with HostInventoryReportJob - Update TasksController to reference HostInventoryReportJob - Update rake task (rh_cloud_inventory:report:generate_upload) - Update GenerateAllReportsJob scheduled task - Update frontend URL in ForemanInventoryHelpers.js - Add report_file_path support to task_json - Remove obsolete controller actions and routes - Delete ReportsController#last action - Delete UploadsController#last action - Remove routes for /reports/last and /uploads/last - Delete obsolete backend files and tests - lib/foreman_inventory_upload/async/generate_report_job.rb - lib/foreman_inventory_upload/async/shell_process.rb - test/jobs/generate_report_job_test.rb - test/unit/shell_process_job_test.rb - test/controllers/reports_controller_test.rb - test/controllers/uploads_controller_test.rb This addresses PR feedback from qcjames53 on theforeman#1127 and backports deletions from part3 to reduce part3 PR size by 52%. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
|
Added input validation for organization_id, limit, and disconnected parameters as requested. Also backported deletions from part3 (GenerateReportJob → HostInventoryReportJob transition) to reduce part3 PR size by 52%. |
|
@qcjames53 thanks for the reviews! Updated. To address your comments about unused code I pulled in some of the changes from part3 to part2. |
|
Awesome! Yeah, I forgot that might be the case for unused code since this was a multi-parter. I can probably put a few hours into this review tomorrow afternoon depending on how other things go; you can expect movement then :) |
qcjames53
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Damn this PR got hands
app/controllers/foreman_inventory_upload/api/tasks_controller.rb
Outdated
Show resolved
Hide resolved
app/controllers/foreman_inventory_upload/api/tasks_controller.rb
Outdated
Show resolved
Hide resolved
app/controllers/foreman_inventory_upload/api/tasks_controller.rb
Outdated
Show resolved
Hide resolved
app/controllers/foreman_inventory_upload/api/tasks_controller.rb
Outdated
Show resolved
Hide resolved
webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js
Outdated
Show resolved
Hide resolved
webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js
Outdated
Show resolved
Hide resolved
webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js
Outdated
Show resolved
Hide resolved
This commit introduces a modernized UI for inventory upload tasks using
PatternFly components and removes obsolete code from the previous
implementation.
**New Components:**
- TaskProgress: Shows current task state with progress bar, status, and duration
- TaskHistory: Displays historical task results in a clean list format
- TasksController API: Provides endpoints for current and historical task data
**UI Improvements:**
- Replace ProgressOutput-based status tracking with ForemanTasks directly
- Add accessibility features (ouiaId properties on PatternFly components)
- Use Patternfly Card, Progress, and DataList components
- Simplify Dashboard to use NavContainer with TaskProgress components
**Backend Changes:**
- Add API endpoints for task data: /api/v2/rh_cloud/inventory_upload/tasks/{current,history}
- Update AccountsController to return task objects instead of status strings
- Maintain backward compatibility with status strings for gradual migration
**Code Cleanup:**
- Remove obsolete DashboardActions, DashboardSelectors, and related Redux code
- Delete unused ProgressOutput registration and instance_label logic
- Remove unnecessary activeTab state management
- Clean up test files for deleted functionality
**Test Updates:**
- Update AccountsControllerTest to match new API structure
- Remove tests for deleted ProgressOutput functionality
- Add new API routes to permissions test exceptions
- All tests passing: 363 tests, 1203 assertions, 0 failures
This change is part of a larger UI redesign effort to improve the user
experience and maintainability of the inventory upload feature.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
- Add input validation to TasksController and ReportsController - Validate organization_id parameter (type and existence) - Add bounds checking for limit parameter (1-100) - Use Foreman::Cast.to_bool for disconnected parameter - Return proper HTTP error codes (400, 404) - Replace obsolete GenerateReportJob with HostInventoryReportJob - Update TasksController to reference HostInventoryReportJob - Update rake task (rh_cloud_inventory:report:generate_upload) - Update GenerateAllReportsJob scheduled task - Update frontend URL in ForemanInventoryHelpers.js - Add report_file_path support to task_json - Remove obsolete controller actions and routes - Delete ReportsController#last action - Delete UploadsController#last action - Remove routes for /reports/last and /uploads/last - Delete obsolete backend files and tests - lib/foreman_inventory_upload/async/generate_report_job.rb - lib/foreman_inventory_upload/async/shell_process.rb - test/jobs/generate_report_job_test.rb - test/unit/shell_process_job_test.rb - test/controllers/reports_controller_test.rb - test/controllers/uploads_controller_test.rb This addresses PR feedback from qcjames53 on theforeman#1127 and backports deletions from part3 to reduce part3 PR size by 52%. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
5db17a6 to
faa20bb
Compare
Backend improvements: - Fix indentation in tasks_controller.rb - Extract duplicate ACTION_TYPES constant - Modernize .try(:duration) to .duration syntax - Add comprehensive test coverage for HostInventoryReportJob: - organization() method - resource_locks() method - report_file_path() with 6 scenarios - Remove empty setup block from test file Frontend improvements: - Add defensive error handling in Dashboard.js for null/undefined account - Enhance Dashboard tests with detailed prop assertions - Add 3 new tests for error handling scenarios All tests passing: - Backend: 22 tests, 55 assertions, 0 failures - Frontend: 4 tests, all passing - Eslint: clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add complete PropTypes to TaskHistory (label, action, state, ended_at, progress, humanized, report_file_path) - Replace window.tfm.toastNotifications with addToast dispatch - Refactor duplicate button code into renderGenerateButtons() helper - Add ouiaId="task-progress-bar" to Progress component - Add edge case protections (API response validation, null checks for started_at) - Fix prettier formatting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
|
@qcjames53 Updated 👍 |
qcjames53
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few outstanding comments that need to be addressed. The other requested changes seem good to me; all tests passing locally.
webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js
Outdated
Show resolved
Hide resolved
webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js
Outdated
Show resolved
Hide resolved
|
@jeremylenz I'm unable to un-resolve the five comments above but the issues are still outstanding. |
Add controller_permission method to require :view_foreman_rh_cloud permission for the API tasks controller endpoints (current and history). Also update the plugin permission definition to include the new foreman_inventory_upload/api/tasks controller actions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add controller_permission method to require :view_foreman_rh_cloud permission for the accounts controller index action. The permission definition was already configured in plugin.rb. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add controller_permission and action_permission methods to require :generate_foreman_rh_cloud permission for the generate action. The permission definition was already configured in plugin.rb. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add ouiaId="task-progress-details" to the DescriptionList component for better test automation support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Change organizationId PropType from oneOfType([string, number]) to just number, since the backend always returns organization.id as a number and all usage is via string interpolation which works fine with numbers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Remove ouiaId from Progress component as it doesn't properly support this prop in PatternFly v5 and causes a React warning about unrecognized props on DOM elements. Keep ouiaId on DescriptionList and Card components for test automation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
5e2b48a to
0c11b77
Compare
|
@qcjames53 Updated. I think I got 'em all this time. (either addressed or replied to.) Let me know if it works for you |
|
Thanks! I'll take a look tomorrow! |
qcjames53
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave this the final once-over and the PR looks good to me! The new ForemanTasks additions, /api/v2/rh_cloud/inventory_upload/tasks/current, and /api/v2/rh_cloud/inventory_upload/tasks/history all work well and seem robust. The new components in the UI for the inventory upload dashboard looks pretty snazzy to me as well. As I understand it we're certain that page is getting cleaned up before we ship a major version.
I'm sure I missed MULTIPLE issues but we can always go back and fix bugs later if need be. We're looking solid, though. Thank you for all the work you put into this, Jeremy.
|
Testing wise it works great, tested with |
Are those still there? If so they will definitely be removed in part 3, which is the followup PR that I am opening right after this is merged. Or if you prefer I can just combine them now. but I don't want to ruin @qcjames53's life |
Let's push it to part 3 that you will open up next, I don't want to throw anything new into the mix since it's already beefy |
chris1984
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked through all the code and most of the stuff that jumped out is what @qcjames53 commented on. I am sure I missed a few things but with this pr having hands and being beefy we can fix things in part 3 like the tabs I mentioned. Tested and works well and looks a hell of a lot better than the old page. ACK

Inventory Upload Page Redesign - PR 2 of 3
User Impact:
This PR removes the old terminal-style progress output UI and replaces it with modern PatternFly components that show task progress, status, and history in a clear, user-friendly format.
What Changed:
Technical Details:
/api/v2/rh_cloud/inventory_upload/tasks/{current,history}🤖 Generated with Claude Code
Co-Authored-By: Claude [email protected]