import React, { useState } from 'react'; import { Modal, Button, Dropdown, DropdownItem, DropdownToggle, DropdownDirection, DropdownToggleAction } from '@patternfly/react-core'; import { CaretDownIcon, CaretUpIcon } from '@patternfly/react-icons'; import { useSelector, useDispatch } from 'react-redux'; import { FormattedMessage } from 'react-intl'; import { Thead, Th, Tbody, Tr, Td, TableVariant } from '@patternfly/react-table'; import { noop } from 'foremanReact/common/helpers'; import { translate as __ } from 'foremanReact/common/I18n'; import { urlBuilder } from 'foremanReact/common/urlHelpers'; import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors'; import PropTypes from 'prop-types'; import TableWrapper from '../../../../Table/TableWrapper'; import { useBulkSelect } from '../../../../Table/TableHooks'; import { HOST_YUM_INSTALLABLE_PACKAGES_KEY } from './YumInstallablePackagesConstants'; import { selectHostYumInstallablePackagesStatus } from './YumInstallablePackagesSelectors'; import { getHostYumInstallablePackages } from './YumInstallablePackagesActions'; import './PackageInstallModal.scss'; import { installPackageBySearch } from '../RemoteExecutionActions'; import { katelloPackageInstallBySearchUrl, katelloPackageInstallUrl } from '../customizedRexUrlHelpers'; import hostIdNotReady from '../../HostDetailsActions'; import { installPackageViaKatelloAgent } from './HostPackagesActions'; const InstallDropdown = ({ isDisabled, installViaRex, installViaKatelloAgent, bulkCustomizedRexUrl, showKatelloAgent, disableInstallViaKatelloAgent, }) => { const [isActionOpen, setIsActionOpen] = useState(false); const onActionSelect = () => { setIsActionOpen(false); }; const onActionToggle = () => { setIsActionOpen(prev => !prev); }; const dropdownItems = [ {__('Install via katello-agent')} , {__('Install via remote execution')} , {__('Install via customized remote execution')} , ]; if (!showKatelloAgent) dropdownItems.shift(); const defaultRemoteAction = showKatelloAgent ? installViaKatelloAgent : installViaRex; return ( Install , ]} splitButtonVariant="action" toggleIndicator={isActionOpen ? CaretUpIcon : CaretDownIcon} onToggle={onActionToggle} /> } isOpen={isActionOpen} dropdownItems={dropdownItems} /> ); }; InstallDropdown.propTypes = { isDisabled: PropTypes.bool, installViaRex: PropTypes.func, installViaKatelloAgent: PropTypes.func, bulkCustomizedRexUrl: PropTypes.string, showKatelloAgent: PropTypes.bool, disableInstallViaKatelloAgent: PropTypes.bool, }; InstallDropdown.defaultProps = { isDisabled: false, installViaRex: noop, installViaKatelloAgent: noop, bulkCustomizedRexUrl: '', showKatelloAgent: false, disableInstallViaKatelloAgent: false, }; const PackageInstallModal = ({ isOpen, closeModal, hostId, hostName, showKatelloAgent, }) => { const emptyContentTitle = __('No packages available to install'); const emptyContentBody = __('No packages available to install on this host. Please check the host\'s content view and lifecycle environment.'); const emptySearchTitle = __('No matching packages found'); const emptySearchBody = __('Try changing your search settings.'); const columnHeaders = ['', __('Package'), __('Version')]; const response = useSelector(state => selectAPIResponse(state, HOST_YUM_INSTALLABLE_PACKAGES_KEY)); const status = useSelector(state => selectHostYumInstallablePackagesStatus(state)); const dispatch = useDispatch(); const { results, ...metadata } = response; const [suppressFirstFetch, setSuppressFirstFetch] = useState(false); const { searchQuery, updateSearchQuery, isSelected, selectOne, selectNone, fetchBulkParams, isSelectable, selectedCount, selectedResults, ...selectAll } = useBulkSelect({ results, metadata }); const fetchItems = (params) => { if (!hostId) return hostIdNotReady; if (results?.length > 0 && suppressFirstFetch) { // If the modal has already been opened, no need to re-fetch the data that's already present setSuppressFirstFetch(false); return { type: 'HOST_APPLICABLE_PACKAGES_NOOP' }; } return getHostYumInstallablePackages(hostId, params); }; const selectedPackageNames = () => selectedResults.map(({ name }) => name); const installViaRex = () => { dispatch(installPackageBySearch({ hostname: hostName, search: fetchBulkParams() })); selectNone(); closeModal(); }; const installViaKatelloAgent = () => { dispatch(installPackageViaKatelloAgent(hostId, { packages: selectedPackageNames() })); selectNone(); closeModal(); }; const handleModalClose = () => { setSuppressFirstFetch(true); closeModal(); }; const bulkCustomizedRexUrl = selectedCount ? katelloPackageInstallBySearchUrl({ hostname: hostName, search: fetchBulkParams() }) : '#'; const simpleBulkCustomizedRexUrl = katelloPackageInstallUrl({ hostname: hostName, packages: selectedPackageNames() }); const enableSimpleRexUrl = !!selectedResults.length; const modalActions = ([ , Cancel , ]); return ( {hostName}, }} /> {columnHeaders.map(col => {col})} {results?.map((pkg, rowIndex) => { const { id, name: packageName, rpm_id: rpmId, version, } = pkg; return ( selectOne(selected, id, pkg), rowIndex, variant: 'checkbox', }} /> {rpmId ? {packageName} : packageName } {version} ); }) } ); }; PackageInstallModal.propTypes = { isOpen: PropTypes.bool.isRequired, closeModal: PropTypes.func.isRequired, hostId: PropTypes.number.isRequired, hostName: PropTypes.string.isRequired, showKatelloAgent: PropTypes.bool, }; PackageInstallModal.defaultProps = { showKatelloAgent: false, }; export default PackageInstallModal;