webpack/components/extensions/HostDetails/Tabs/PackagesTab.js in katello-4.3.1 vs webpack/components/extensions/HostDetails/Tabs/PackagesTab.js in katello-4.4.0.rc1

- old
+ new

@@ -1,26 +1,53 @@ import React, { useCallback, useState } from 'react'; import { useSelector } from 'react-redux'; -import { Button, Hint, HintBody } from '@patternfly/react-core'; +import { + Button, + Hint, + HintBody, + DropdownItem, + DropdownSeparator, + Dropdown, + Skeleton, + Split, + SplitItem, + ActionList, + ActionListItem, + KebabToggle, +} from '@patternfly/react-core'; import { TableVariant, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-table'; import { translate as __ } from 'foremanReact/common/I18n'; import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors'; import { urlBuilder } from 'foremanReact/common/urlHelpers'; +import SelectableDropdown from '../../../SelectableDropdown'; import TableWrapper from '../../../../components/Table/TableWrapper'; +import { useUrlParams } from '../../../../components/Table/TableHooks'; import { PackagesStatus, PackagesLatestVersion } from '../../../../components/Packages'; import { getInstalledPackagesWithLatest } from '../HostPackages/HostPackagesActions'; import { selectHostPackagesStatus } from '../HostPackages/HostPackagesSelectors'; -import { HOST_PACKAGES_KEY } from '../HostPackages/HostPackagesConstants'; +import { HOST_PACKAGES_KEY, PACKAGES_VERSION_STATUSES, VERSION_STATUSES_TO_PARAM } from '../HostPackages/HostPackagesConstants'; import './PackagesTab.scss'; +import hostIdNotReady from '../HostDetailsActions'; +import PackageInstallModal from './PackageInstallModal'; +import defaultRemoteActionMethod, { KATELLO_AGENT } from '../hostDetailsHelpers'; export const PackagesTab = () => { const hostDetails = useSelector(state => selectAPIResponse(state, 'HOST_DETAILS')); - const { id: hostId } = hostDetails; - const actionButtons = <Button isDisabled> {__('Upgrade')} </Button>; + const { id: hostId, name: hostName } = hostDetails; - const [searchQuery, updateSearchQuery] = useState(''); + const { searchParam } = useUrlParams(); + const [searchQuery, updateSearchQuery] = useState(searchParam || ''); + const PACKAGE_STATUS = __('Status'); + const [packageStatusSelected, setPackageStatusSelected] = useState(PACKAGE_STATUS); + const activeFilters = [packageStatusSelected]; + const defaultFilters = [PACKAGE_STATUS]; + const [isBulkActionOpen, setIsBulkActionOpen] = useState(false); + const toggleBulkAction = () => setIsBulkActionOpen(prev => !prev); + const [isModalOpen, setIsModalOpen] = useState(false); + const closeModal = () => setIsModalOpen(false); + const showKatelloAgent = (defaultRemoteActionMethod({ hostDetails }) === KATELLO_AGENT); const emptyContentTitle = __('This host does not have any packages.'); const emptyContentBody = __('Packages will appear here when available.'); const emptySearchTitle = __('No matching packages found'); const emptySearchBody = __('Try changing your search settings.'); @@ -30,26 +57,104 @@ __('Installed Version'), __('Upgradable To'), ]; const fetchItems = useCallback( - params => (hostId ? getInstalledPackagesWithLatest(hostId, params) : null), - [hostId], + (params) => { + if (!hostId) return hostIdNotReady; + const modifiedParams = { ...params }; + if (packageStatusSelected !== PACKAGE_STATUS) { + modifiedParams.status = VERSION_STATUSES_TO_PARAM[packageStatusSelected]; + } + return getInstalledPackagesWithLatest(hostId, modifiedParams); + }, + [hostId, PACKAGE_STATUS, packageStatusSelected], ); const response = useSelector(state => selectAPIResponse(state, HOST_PACKAGES_KEY)); const { results, ...metadata } = response; const status = useSelector(state => selectHostPackagesStatus(state)); + + if (!hostId) return <Skeleton />; + const handleInstallPackagesClick = () => { + setIsBulkActionOpen(false); + setIsModalOpen(true); + }; + const rowActions = [ { title: __('Upgrade via remote execution'), disabled: true, }, { title: __('Upgrade via customized remote execution'), disabled: true, }, ]; + const handlePackageStatusSelected = newStatus => setPackageStatusSelected((prevStatus) => { + if (prevStatus === newStatus) { + return PACKAGE_STATUS; + } + return newStatus; + }); + + const toggleGroup = ( + <Split hasGutter> + <SplitItem> + <SelectableDropdown + id="package-status-dropdown" + title={PACKAGE_STATUS} + showTitle={false} + items={Object.values(PACKAGES_VERSION_STATUSES)} + selected={packageStatusSelected} + setSelected={handlePackageStatusSelected} + /> + </SplitItem> + </Split> + ); + + const dropdownItems = [ + <DropdownItem + aria-label="remove_pkg_from_host" + key="remove_pkg_from_host" + component="button" + isDisabled + > + {__('Remove')} + </DropdownItem>, + <DropdownSeparator key="separator" />, + <DropdownItem + aria-label="install_pkg_on_host" + key="install_pkg_on_host" + component="button" + onClick={handleInstallPackagesClick} + > + {__('Install packages')} + </DropdownItem>, + ]; + + const actionButtons = ( + <> + <Split hasGutter> + <SplitItem> + <ActionList isIconList> + <ActionListItem> + <Button isDisabled> {__('Upgrade')} </Button> + </ActionListItem> + <ActionListItem> + <Dropdown + toggle={<KebabToggle aria-label="Packages bulk actions" onToggle={toggleBulkAction} />} + isOpen={isBulkActionOpen} + isPlain + dropdownItems={dropdownItems} + /> + </ActionListItem> + </ActionList> + </SplitItem> + </Split> + </> + ); + return ( <div> <div id="packages-hint" className="margin-0-24 margin-top-16"> <Hint> <HintBody> @@ -68,16 +173,19 @@ emptyContentTitle, emptyContentBody, emptySearchTitle, emptySearchBody, status, + activeFilters, + defaultFilters, actionButtons, searchQuery, updateSearchQuery, + toggleGroup, } } - additionalListeners={[hostId]} + additionalListeners={[hostId, packageStatusSelected]} fetchItems={fetchItems} autocompleteEndpoint={`/hosts/${hostId}/packages/auto_complete_search`} foremanApiAutoComplete variant={TableVariant.compact} > @@ -118,9 +226,18 @@ }) } </Tbody> </TableWrapper> </div> + {hostId && + <PackageInstallModal + isOpen={isModalOpen} + closeModal={closeModal} + hostId={hostId} + hostName={hostName} + showKatelloAgent={showKatelloAgent} + /> + } </div> ); }; export default PackagesTab;