Skip to content

Fixes #38165 - Add checkboxes and related actions: open all, rerun, open all failed#944

Merged
adamruzicka merged 1 commit into
theforeman:masterfrom
kmalyjur:job-inv-table-checkboxes-clean
Jul 16, 2025
Merged

Fixes #38165 - Add checkboxes and related actions: open all, rerun, open all failed#944
adamruzicka merged 1 commit into
theforeman:masterfrom
kmalyjur:job-inv-table-checkboxes-clean

Conversation

@kmalyjur

@kmalyjur kmalyjur commented Jan 28, 2025

Copy link
Copy Markdown
Contributor
  • Adds checkboxes to the table
  • Modifies the button and modal for opening selected hosts in a new tab
  • Adds a button for rerunning selected hosts
  • Adds a kebab dropdown for opening all failed hosts in a new tab

Canceling and aborting + tests for the table functionality will be added in a new PR.

image

collection @hosts

attribute :name, :operatingsystem_id, :operatingsystem_name, :hostgroup_id, :hostgroup_name, :id
attribute :id, :name, :operatingsystem_id, :operatingsystem_name, :hostgroup_id, :hostgroup_name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nope, just wrong rebase, sorry

Comment on lines +69 to +71
`Task for the host ${
action === 'cancel' ? 'cancelled' : 'aborted'
} successfully`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please ues 2 different strings so we wont have to do difficult translations

@adamruzicka adamruzicka 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.

Selecting the rows one by one and clicking rerun works.

Selecting all, then unchecking one and clicking rerun runs it only on the one that was unselected.

Selecting all and clicking rerun doesn't do anything, even though the button appears active.

Comment on lines +250 to +268
<OpenAlInvocations
setShowAlert={setShowAlert}
results={results}
id={id}
/>
}
/>,
<CheckboxesActions
jobID={id}
bulkParams={bulkParams}
failedHosts={failedHosts}
selectedCount={selectedCount}
currentPermissions={currentPermissions}
permissionsStatus={permissionsStatus}
/>,
]}
controller="hosts"
creatable={false}
replacementResponse={combinedResponse}
selectionToolbar={selectionToolbar}
updateSearchQuery={updateSearchQueryBulk}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

need key props

targeting: PropTypes.object.isRequired,
finished: PropTypes.bool.isRequired,
autoRefresh: PropTypes.bool.isRequired,
initialFilter: PropTypes.string.isRequired,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

 The prop `initialFilter` is marked as required in `JobInvocationHostTable`, but its value is `undefined`.


return (
<>
<RerunButton />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you please space between rerun and open all in new tabs?
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Of course, sorry, I haven't even looked at it after rebasing

onClick={() => {
if (failedHosts.length <= 3) {
failedHosts.forEach(id =>
openLink(`/job_invocations/${id}`, () => {})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should open /show_template_invocation_by_host/:host_id/job_invocation/:id

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from fe71baf to 121976e Compare February 12, 2025 10:39
@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from 121976e to 6c1ce3a Compare March 10, 2025 11:38
@kmalyjur kmalyjur changed the title Fixes #38165 - Add checkboxes actions to job invocation page Fixes #38165 - Add checkboxes to job invocation page Mar 10, 2025
@kmalyjur
kmalyjur marked this pull request as ready for review March 10, 2025 12:55
@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from 6c1ce3a to ccdd86d Compare March 10, 2025 14:21

@MariaAga MariaAga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the addition! I did an initial review but will need to do another one once its all addressed

section:nth-child(1) {
padding: 0;
}
.open-all-button {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you make it more centered in the line height middle?
image

Comment on lines +220 to +221
<ToolbarItem key="selectAll">
<SelectAllCheckbox

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also can you make the selectall be aligned with the search?
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This one might be on me in foreman core

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

<Modal
ouiaId="template-invocation-new-tab-modal"
title={__('Open all invocations in new tabs')}
title={__('Open all selected invocations in new tabs')}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The modal is a bit too small for the new title, could you make the modal bigger? (or add some wrap css)
image

onClick={() => {
results.forEach(result => {
idsArray.forEach(result => {
openLink(templateInvocationPageUrl(result.id, id), '_blank');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should also be openLink(templateInvocationPageUrl(result, id), '_blank'); as the previous one

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be good to test that the window.open mock function has been called on click, with the right url

const OpenAllButton = () => (
<Button
variant="link"
isDisabled={idsArray.length === 0}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Clicking on the select all checkbox doesnt enable the button

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Only if the page has a search *

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from ccdd86d to 1bfeae8 Compare May 14, 2025 17:37
@kmalyjur kmalyjur changed the title Fixes #38165 - Add checkboxes to job invocation page Fixes #38165 - Add checkboxes and related actions: open all, rerun, open all failed May 14, 2025
@kmalyjur

Copy link
Copy Markdown
Contributor Author

Refactored a good bit - updated the PR description accordingly.

@kmalyjur
kmalyjur requested a review from MariaAga May 19, 2025 07:53
Comment thread webpack/JobInvocationDetail/JobInvocationHostTable.js Outdated
@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch 2 times, most recently from 9012e1f to 2cd2e8b Compare June 11, 2025 10:38
@kmalyjur

Copy link
Copy Markdown
Contributor Author

I added a fix for the bottom pagination and also made some changes to the filter functionality.
There is one small issue with the table when changing the page directly in the URL, which I'll resolve in foreman/.../TableIndexPage.js.

@MariaAga MariaAga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I tried to open all failed and the array for hostsToOpen was empty but the modal said The number of failed invocations is: 97

Also if I select all the open in new tab button is disabled

const [isOpenFailed, setIsOpenFailed] = useState(false);
const idsArray = getIdsArray(bulkParams, allHostsIds, isAllSelected);
const permissions = useSelector(
state => selectTemplateInvocation(state)?.permissions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Need to make sure that #968 isnt clashing with this

margin-bottom: -10px;
}

.pf-v5-c-toolbar__group.pf-m-button-group {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This needs to be under the page classname

},
actions: {
title: '',
title: <span className="pf-u-screen-reader">{__('Actions')}</span>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For some reason its not being aligned
image

[DYNAMIC_TYPE]: __('Dynamic Query'),
};

export const getIdsArray = (bulkParams, allHostsIds, isAllSelected) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure, but can you just use inclusionSet, exclusionSet, I think useBulkSelect should send them as well

export const GET_REPORT_TEMPLATE_INPUTS = 'GET_REPORT_TEMPLATE_INPUTS';
export const JOB_INVOCATION_HOSTS = 'JOB_INVOCATION_HOSTS';
export const GET_TEMPLATE_INVOCATION = 'GET_TEMPLATE_INVOCATION';
export const MAX_HOSTS_API_SIZE = 'MAX_HOSTS_API_SIZE';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should probably be a number since hostsToOpen.slice(0, MAX_HOSTS_API_SIZE) doesnt work for a string

@ekohl ekohl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm thinking out loud here. Background is that https://issues.redhat.com/browse/SAT-26318 was opened and after looking at the new job detail page the only feedback was a request to see all output. Not just the failed ones. This PR looks like the closest we have, so I'm commenting here.

If there's a better place then I'll happily hear about that.

  • Should open be for opening in a new tab and use expand to open on the same page?
  • Does it make sense to special case the failed jobs? If you add an action to open/expand all then the user can filter the statuses to only failed.
  • Could it be a bulk action on the selected items?
  • Is it clear enough this opens new tabs? The "open" wording may not be clear and it could open 100 of tabs.

Comment on lines +146 to +149
href={foremanUrl(
`/job_invocations/${jobID}/rerun?${idsArray
.map(id => `host_ids[]=${id}`)
.join('&')}`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does it make sense to use URLSearchParams to construct the query string? I think generally speaking it's a good practice. Here it may not matter that much, but it should deal well with escaping. [] should be escaped.

foremanUrl(`/api/job_invocations/${jobID}/hosts`),
{
params: {
per_page: MAX_HOSTS_API_SIZE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is no pagination. What if there are more than 100 failed hosts? Will the UI give the user the impression it will open more than 100? How do you expect the user to open the ones beyond 100? I'm not sure if all is supported here or even a good idea.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we (or maybe we already do) add an "open selected" button, then users can choose what to open.
I dont think anyone want to open more than 100 tabs.
And anyway users can open in a new tab indevidually.
We warn them about the 100 in the modal "{__('This will open a new tab for each invocation. The maximum is 100.')}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's why I liked the suggestion to expand items in bulk on the page. That's a bit easier to manage than tabs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We can add it in another pr, but the open all failed in tabs was requested specifically

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you know if there is an issue for it now? I'd like to include it somewhere in the larger effort but it doesn't have to be this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@ekohl @MariaAga thank you for your comments!

Regarding SAT-26318 - I closed this one and I've just created SAT-35515.

Should open be for opening in a new tab and use expand to open on the same page?

Yeah I think so and I refer to it like that

We can add it in another pr, but the open all failed in tabs was requested specifically

I agree

Do you know if there is an issue for it now? I'd like to include it somewhere in the larger effort but it doesn't have to be this PR.

You mean for the failed tabs or for expanding the table?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Regarding SAT-26318 - I closed this one and I've just created SAT-35515.

Excellent, thanks.

SAT-26318

Expanding the table, which you just created an issue for.


const handleOpenHosts = async (type = 'all') => {
if (type === 'failed') {
if (failedCount <= 3) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why 3 here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if its less than 3 we just open it in new tabs, if its more than we ask the user if they are sure they want to open X amount of tabs just so no one gets 10 new tabs by accidentally clicking the button

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My programming professor in university always insistent on constants with a descriptive name. Could we do that?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I usually remember him in my reviews 🙃, not enough

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from 2cd2e8b to d2b187b Compare July 7, 2025 11:10
@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from d2b187b to 986687a Compare July 7, 2025 12:01
@kmalyjur

kmalyjur commented Jul 7, 2025

Copy link
Copy Markdown
Contributor Author

The latest push incorporates all of your suggestions. Could you please look at it again?

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from 986687a to ae8b5d9 Compare July 8, 2025 10:03
@kmalyjur
kmalyjur requested a review from MariaAga July 9, 2025 11:34
Comment on lines +9 to +10
import { OutlinedWindowRestoreIcon } from '@patternfly/react-icons';
import EllipsisVIcon from '@patternfly/react-icons/dist/js/icons/ellipsis-v-icon';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please combine them


const fetchFailedHosts = async () => {
const { data } = await axios.get(
foremanUrl(`/api/job_invocations/${jobID}/hosts`),

@MariaAga MariaAga Jul 9, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry this is coming late in the review, took me sometime to find that this is called on tabs open and not on modal open (and I didnt see extra requests until I opened the tabs).
I think instead of axios.get on button click, it should use the Useapi, and then the request wont be repeated and the failed host list will be available to all with redux

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch 2 times, most recently from bedde35 to aebbac4 Compare July 14, 2025 17:44
Comment on lines +86 to +91
`Are you sure you want to open all ${modalText} invocations in new tabs?`
)}
<br />
{__('This will open a new tab for each invocation. The maximum is 100.')}
<br />
{__(`The number of ${modalText} invocations is:`)}{' '}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

onClick={() => handleOpenHosts('failed')}
isDisabled={failedCount === 0}
>
{__(`Open all failed runs (${failedCount})`)}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

also needs sprintf instead

ouiaId="template-invocation-new-tab-button"
variant="link"
>
<Tooltip content="Open selected in new tab">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

needs to be translated

@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from aebbac4 to 5e3883e Compare July 16, 2025 15:03
@kmalyjur
kmalyjur force-pushed the job-inv-table-checkboxes-clean branch from 5e3883e to a0ad547 Compare July 16, 2025 15:35
@adamruzicka
adamruzicka merged commit 9be3621 into theforeman:master Jul 16, 2025
13 of 16 checks passed
@adamruzicka

Copy link
Copy Markdown
Contributor

Thank you @kmalyjur & @MariaAga !

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.

4 participants