Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 39 additions & 30 deletions webpack/JobInvocationDetail/CheckboxesActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,21 @@ import {
} from '@patternfly/react-icons';
import axios from 'axios';
import { foremanUrl } from 'foremanReact/common/helpers';
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
import { translate as __, sprintf } from 'foremanReact/common/I18n';
import { addToast } from 'foremanReact/components/ToastsList';
import PropTypes from 'prop-types';
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import {
DIRECT_OPEN_HOST_LIMIT,
MAX_HOSTS_API_SIZE,
templateInvocationPageUrl,
} from './JobInvocationConstants';
import {
selectHasPermission,
selectTaskCancelable,
} from './JobInvocationSelectors';
import OpenAllInvocationsModal, { PopupAlert } from './OpenAllInvocationsModal';
import OpenAllInvocationsModal from './OpenAllInvocationsModal';

/* eslint-disable camelcase */
const ActionsKebab = ({
Expand Down Expand Up @@ -73,7 +71,7 @@ const ActionsKebab = ({
onClick={() => handleOpenHosts('failed')}
isDisabled={failedCount === 0}
>
{sprintf(__('Open all failed runs (%s)'), failedCount)}
{sprintf(__('Open all failed runs on this page (%s)'), failedCount)}
</DropdownItem>,
];

Expand Down Expand Up @@ -104,17 +102,18 @@ const ActionsKebab = ({

export const CheckboxesActions = ({
selectedIds,
failedCount,
allJobs,
jobID,
filter,
bulkParams,
setShowAlert,
}) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [showAlert, setShowAlert] = useState(false);
const [isOpenFailed, setIsOpenFailed] = useState(false);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const isTaskCancelable = useSelector(selectTaskCancelable);
const dispatch = useDispatch();
const [toBeOpened, setToBeOpened] = useState([]);

const hasCreatePermission = useSelector(
selectHasPermission('create_job_invocations')
Expand All @@ -129,19 +128,14 @@ export const CheckboxesActions = ({
: '';
const combinedQuery = `${bulkParams}${filterQuery}`;

const { response: failedHostsData } = useAPI(
'get',
foremanUrl(`/api/job_invocations/${jobID}/hosts`),
{
params: {
per_page: MAX_HOSTS_API_SIZE,
search: `job_invocation.result = failed`,
},
skip: failedCount === 0,
}
);
const [failedHosts, setFailedHosts] = useState([]);

const failedHosts = failedHostsData?.results || [];
useEffect(() => {
const failed = allJobs.filter(i => i.job_status === 'error');
setFailedHosts(failed);
}, [allJobs]);

const failedCount = failedHosts.length;

const openLink = url => {
const newWin = window.open(url);
Expand All @@ -151,24 +145,35 @@ export const CheckboxesActions = ({
}
};

const openTabs = tabs => {
tabs.forEach(open => {
const openId = open.id ?? open;
openLink(templateInvocationPageUrl(openId, jobID));
});
};

const handleOpenHosts = async (type = 'all') => {
if (type === 'failed') {
if (failedCount <= DIRECT_OPEN_HOST_LIMIT) {
failedHosts.forEach(host =>
openLink(templateInvocationPageUrl(host.id, jobID))
);
openTabs(failedHosts);
return;
}
setToBeOpened(failedHosts);
setIsOpenFailed(true);
setIsModalOpen(true);
return;
}

if (selectedIds.length === 0) {
selectedIds = allJobs;
}

if (selectedIds.length <= DIRECT_OPEN_HOST_LIMIT) {
selectedIds.forEach(id => openLink(templateInvocationPageUrl(id, jobID)));
openTabs(selectedIds);
return;
}

setToBeOpened(selectedIds);
setIsOpenFailed(false);
setIsModalOpen(true);
};
Expand Down Expand Up @@ -237,13 +242,19 @@ export const CheckboxesActions = ({
<Button
aria-label="open all template invocations in new tab"
className="open-all-button"
isDisabled={selectedIds.length === 0}
isDisabled={allJobs.length === 0}
isInline
onClick={() => handleOpenHosts('all')}
ouiaId="template-invocation-new-tab-button"
variant="link"
>
<Tooltip content={__('Open selected in new tab')}>
<Tooltip
content={
selectedIds.length === 0
? __('Open all rows of the table in new tabs')
: __('Open selected in new tab')
}
>
<OutlinedWindowRestoreIcon />
</Tooltip>
</Button>
Expand Down Expand Up @@ -281,16 +292,13 @@ export const CheckboxesActions = ({
isDropdownOpen={isDropdownOpen}
setIsDropdownOpen={setIsDropdownOpen}
/>
{showAlert && <PopupAlert setShowAlert={setShowAlert} />}
<OpenAllInvocationsModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
failedCount={failedCount}
failedHosts={failedHosts}
jobID={jobID}
isOpenFailed={isOpenFailed}
setShowAlert={setShowAlert}
selectedIds={selectedIds}
confirmCallback={() => openTabs(toBeOpened)}
/>
</>
);
Expand All @@ -314,10 +322,11 @@ ActionsKebab.defaultProps = {

CheckboxesActions.propTypes = {
selectedIds: PropTypes.array.isRequired,
failedCount: PropTypes.number.isRequired,
allJobs: PropTypes.array.isRequired,
jobID: PropTypes.string.isRequired,
bulkParams: PropTypes.string,
filter: PropTypes.string,
setShowAlert: PropTypes.func.isRequired,
};

CheckboxesActions.defaultProps = {
Expand Down
1 change: 0 additions & 1 deletion webpack/JobInvocationDetail/JobInvocationConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const GET_REPORT_TEMPLATES = 'GET_REPORT_TEMPLATES';
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 = 100;
export const DIRECT_OPEN_HOST_LIMIT = 3;
export const ALL_JOB_HOSTS = 'ALL_JOB_HOSTS';
export const currentPermissionsUrl = foremanUrl(
Expand Down
Loading
Loading