diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
index e318b2c4cda9..84e00cdc82f9 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
@@ -1,29 +1,140 @@
import React from 'react';
import { CubeIcon } from '@patternfly/react-icons';
+import { Td } from '@patternfly/react-table';
+import {
+ Dropdown,
+ KebabToggle,
+ DropdownItem,
+ ToolbarItem,
+} from '@patternfly/react-core';
import { translate as __ } from '../../common/I18n';
import TableIndexPage from '../PF4/TableIndexPage/TableIndexPage';
+import { ActionKebab } from '../PF4/TableIndexPage/ActionKebab';
import { HOSTS_API_PATH, API_REQUEST_KEY } from '../../routes/Hosts/constants';
+import { useAPI } from '../../common/hooks/API/APIHooks';
+import { useBulkSelect } from '../PF4/TableIndexPage/Table/TableHooks';
+import SelectAllCheckbox from '../PF4/TableIndexPage/Table/SelectAllCheckbox';
+import { getPageStats } from '../PF4/TableIndexPage/Table/helpers';
+import { STATUS } from '../../constants';
const HostsIndex = () => {
const columns = {
name: {
title: __('Name'),
- wrapper: ({ id, name }) => ({name}),
+ wrapper: ({ id, name }) => {name},
isSorted: true,
},
};
+ const defaultParams = { search: '' }; // search ||
+
+ const response = useAPI(
+ 'get',
+ HOSTS_API_PATH.includes('include_permissions')
+ ? HOSTS_API_PATH
+ : `${HOSTS_API_PATH}?include_permissions=true`,
+ {
+ ...{ key: API_REQUEST_KEY },
+ params: defaultParams,
+ }
+ );
+
+ const {
+ response: {
+ search: apiSearchQuery,
+ can_create: canCreate,
+ results,
+ total,
+ per_page: perPage,
+ page,
+ subtotal,
+ message: errorMessage,
+ },
+ status = STATUS.PENDING,
+ setAPIOptions,
+ } = response;
+
+ const { pageRowCount } = getPageStats({ total, page, perPage });
+
+ const {
+ updateSearchQuery,
+ fetchBulkParams,
+ ...selectAllOptions
+ } = useBulkSelect({
+ results,
+ metadata: {},
+ });
+
+ const {
+ selectAll,
+ selectPage,
+ selectNone,
+ selectedCount,
+ selectOne,
+ areAllRowsOnPageSelected,
+ areAllRowsSelected,
+ isSelected,
+ } = selectAllOptions;
const computeContentSource = search =>
`/change_host_content_source?search=${search}`;
- const customActionKebabs = [
- {
- title: __('Change content source'),
- icon: ,
- computeHref: computeContentSource,
- },
+ const item = {
+ title: __('Change content source'),
+ icon: ,
+ computeHref: computeContentSource,
+ };
+
+ const selectionToolbar = (
+
+
+
+ );
+
+ const rowSelectNodeFunc = result => (
+
{
+ selectOne(isSelecting, result.id);
+ },
+ isSelected: isSelected(result.id),
+ disable: false,
+ }}
+ />
+ );
+
+ const computeHref = () => {
+ if (selectedCount > 0) {
+ return `/change_host_content_source?search=${fetchBulkParams()}`;
+ }
+ return '';
+ };
+
+ const actionNode = [
+
+ {item.icon} {item.title}
+ ,
];
+ const customToolbarItems = ;
+
return (
{
controller="hosts"
isDeleteable
columns={columns}
- displaySelectAllCheckbox
- customActionKebabs={customActionKebabs}
creatable={false}
+ response={response}
+ customToolbarItems={customToolbarItems}
+ selectionToolbar={selectionToolbar}
+ rowSelectNodeFunc={rowSelectNodeFunc}
/>
);
};
diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionButtons.js b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionButtons.js
index fe4c287ca79c..c285d27d042c 100644
--- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionButtons.js
+++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionButtons.js
@@ -1,6 +1,11 @@
-import React from 'react';
+import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { Button } from '@patternfly/react-core';
+import {
+ Button,
+ Dropdown,
+ KebabToggle,
+ DropdownItem,
+} from '@patternfly/react-core';
/**
* Generate a button or a dropdown of buttons
@@ -10,20 +15,43 @@ import { Button } from '@patternfly/react-core';
*/
export const ActionButtons = ({ buttons: originalButtons }) => {
const buttons = [...originalButtons];
+ const [isOpen, setIsOpen] = useState(false);
if (!buttons.length) return null;
-
- const pfButtons = buttons.map(button => (
-
- ));
-
- return <>{pfButtons}>;
+ const firstButton = buttons.shift();
+ return (
+ <>
+
+ {buttons.length > 0 && (
+
+ }
+ isOpen={isOpen}
+ isPlain
+ dropdownItems={buttons.map(button => (
+
+ {button.icon} {button.title}
+
+ ))}
+ />
+ )}
+ >
+ );
};
ActionButtons.propTypes = {
@@ -32,7 +60,6 @@ ActionButtons.propTypes = {
action: PropTypes.object,
title: PropTypes.string,
icon: PropTypes.node,
- isDisabled: PropTypes.bool,
})
),
};
diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionKebab.js b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionKebab.js
index 0238acf399fc..bfce80789a67 100644
--- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionKebab.js
+++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionKebab.js
@@ -8,8 +8,7 @@ import { Dropdown, KebabToggle, DropdownItem } from '@patternfly/react-core';
* @param {Object} action action to preform when the button is click can be href with data-method or Onclick
* @return {Function} button component or splitbutton component
*/
-export const ActionKebab = ({ items: originalItems }) => {
- const items = [...originalItems];
+export const ActionKebab = ({ items }) => {
const [isOpen, setIsOpen] = useState(false);
if (!items.length) return null;
return (
@@ -25,17 +24,7 @@ export const ActionKebab = ({ items: originalItems }) => {
}
isOpen={isOpen}
isPlain
- dropdownItems={items.map(item => (
-
- {item.icon} {item.title}
-
- ))}
+ dropdownItems={items}
/>
)}
>
@@ -43,14 +32,7 @@ export const ActionKebab = ({ items: originalItems }) => {
};
ActionKebab.propTypes = {
- items: PropTypes.arrayOf(
- PropTypes.shape({
- action: PropTypes.object,
- title: PropTypes.string,
- icon: PropTypes.node,
- isDisabled: PropTypes.bool,
- })
- ),
+ items: PropTypes.arrayOf(PropTypes.node),
};
ActionKebab.defaultProps = {
diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/Table.js b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/Table.js
index 2b511c6b4efa..a6de46c2c606 100644
--- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/Table.js
+++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/Table.js
@@ -29,9 +29,7 @@ export const Table = ({
url,
isPending,
isEmbedded,
- displaySelectAllCheckbox,
- isSelected,
- selectOne,
+ rowSelectNodeFunc,
}) => {
const columnsToSortParams = {};
Object.keys(columns).forEach(key => {
@@ -86,7 +84,7 @@ export const Table = ({
- {displaySelectAllCheckbox && | }
+ {rowSelectNodeFunc && | }
{columnNamesKeys.map(k => (
(
|
- {displaySelectAllCheckbox && (
- {
- selectOne(isSelecting, result.id);
- },
- isSelected: isSelected(result.id),
- disable: false,
- }}
- />
- )}
+ {rowSelectNodeFunc && rowSelectNodeFunc(result)}
{columnNamesKeys.map(k => (
|
{columns[k].wrapper ? columns[k].wrapper(result) : result[k]}
@@ -183,9 +170,7 @@ Table.propTypes = {
url: PropTypes.string.isRequired,
isPending: PropTypes.bool.isRequired,
isEmbedded: PropTypes.bool,
- displaySelectAllCheckbox: PropTypes.bool,
- isSelected: PropTypes.func,
- selectOne: PropTypes.func,
+ rowSelectNodeFunc: PropTypes.func,
};
Table.defaultProps = {
@@ -193,9 +178,7 @@ Table.defaultProps = {
isDeleteable: false,
itemCount: 0,
getActions: null,
+ rowSelectNodeFunc: undefined,
results: [],
isEmbedded: false,
- displaySelectAllCheckbox: false,
- selectOne: noop,
- isSelected: noop,
};
diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/TableHooks.js b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/TableHooks.js
index 20c2ad30d276..a5506cea1754 100644
--- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/TableHooks.js
+++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/TableHooks.js
@@ -215,7 +215,6 @@ export const useBulkSelect = ({
};
const selectAll = checked => {
- console.log({ checked });
setSelectAllMode(checked);
if (checked) {
exclusionSet.clear();
@@ -225,7 +224,6 @@ export const useBulkSelect = ({
};
const fetchBulkParams = (idColumnName = idColumn) => {
- console.log('fetchBulkParams');
const searchQueryWithExclusionSet = () => {
const query = [
searchQuery,
@@ -233,7 +231,6 @@ export const useBulkSelect = ({
!isEmpty(exclusionSet) &&
`${idColumnName} !^ (${[...exclusionSet].join(',')})`,
];
- console.log(query.filter(item => item).join(' and '));
return query.filter(item => item).join(' and ');
};
@@ -242,8 +239,6 @@ export const useBulkSelect = ({
throw new Error('Cannot build a search query with no items selected');
return `${idColumnName} ^ (${[...inclusionSet].join(',')})`;
};
-
- console.log({ selectAllMode });
return selectAllMode
? searchQueryWithExclusionSet()
: searchQueryWithInclusionSet();
@@ -299,4 +294,4 @@ export const useUrlParams = () => {
searchParam,
...urlParams,
};
-};
\ No newline at end of file
+};
diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.js b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.js
index 7a1d7f69613a..8212be7d2130 100644
--- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.js
+++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { QuestionCircleIcon } from '@patternfly/react-icons';
import { useHistory } from 'react-router-dom';
import URI from 'urijs';
+import { noop } from '../../../common/helpers';
import {
Spinner,
Toolbar,
@@ -14,6 +15,7 @@ import {
TextContent,
Text,
PaginationVariant,
+ Button,
} from '@patternfly/react-core';
import Pagination from '../../Pagination';
@@ -31,7 +33,6 @@ import BreadcrumbBar from '../../BreadcrumbBar';
import SearchBar from '../../SearchBar';
import Head from '../../Head';
import { ActionButtons } from './ActionButtons';
-import { ActionKebab } from './ActionKebab';
import './TableIndexPage.scss';
import { Table } from './Table/Table';
import { useBulkSelect } from './Table/TableHooks';
@@ -85,7 +86,9 @@ const TableIndexPage = ({
isDeleteable,
searchable,
children,
- displaySelectAllCheckbox,
+ selectionToolbar,
+ rowSelectNodeFunc,
+ response,
}) => {
const history = useHistory();
const { location: { search: historySearch } = {} } = history || {};
@@ -115,39 +118,24 @@ const TableIndexPage = ({
},
status = STATUS.PENDING,
setAPIOptions,
- } = useAPI(
- 'get',
- apiUrl.includes('include_permissions')
- ? apiUrl
- : `${apiUrl}?include_permissions=true`,
- {
- ...apiOptions,
- params: defaultParams,
- }
- );
- const { pageRowCount } = getPageStats({ total, page, perPage });
- const {
- updateSearchQuery,
- fetchBulkParams,
- ...selectAllOptions
- } = useBulkSelect({
- results,
- metadata: {},
- });
+ } =
+ response.length > 0
+ ? response
+ : useAPI(
+ 'get',
+ apiUrl.includes('include_permissions')
+ ? apiUrl
+ : `${apiUrl}?include_permissions=true`,
+ {
+ ...apiOptions,
+ params: defaultParams,
+ }
+ );
const onPagination = newPagination => {
setParamsAndAPI({ ...params, ...newPagination });
};
- const {
- selectAll,
- selectPage,
- selectNone,
- selectedCount,
- areAllRowsOnPageSelected,
- areAllRowsSelected,
- } = selectAllOptions;
-
const memoDefaultSearchProps = useMemo(
() => getControllerSearchProps(controller),
[controller]
@@ -176,33 +164,6 @@ const TableIndexPage = ({
}
};
- const processCustomElementActions = buttons =>
- buttons.map(button => {
- const responseButton = { ...button };
-
- if (selectedCount === 0) {
- responseButton.isDisabled = true;
- }
-
- if (
- displaySelectAllCheckbox &&
- responseButton.computeHref &&
- selectedCount > 0
- ) {
- responseButton.action = {
- href: responseButton.computeHref(fetchBulkParams()),
- };
- }
- return responseButton;
- });
-
- const additionalActionButtons = processCustomElementActions(
- customActionButtons
- );
- const additionalActionKebabs = processCustomElementActions(
- customActionKebabs
- );
-
const actionButtons = [
creatable &&
canCreate && {
@@ -220,7 +181,7 @@ const TableIndexPage = ({
icon: ,
action: { href: customHelpURL || helpURL() },
},
- ...additionalActionButtons,
+ ...customActionButtons,
].filter(item => item);
return (
@@ -246,22 +207,7 @@ const TableIndexPage = ({
{searchable && (
- {displaySelectAllCheckbox && (
-
-
-
- )}
+ {selectionToolbar}
)}
- {additionalActionKebabs.length > 0 && (
-
-
-
-
-
- )}
-
{customToolbarItems && (
{customToolbarItems}
)}
@@ -328,8 +266,7 @@ const TableIndexPage = ({
status === STATUS.ERROR && errorMessage ? errorMessage : null
}
isPending={status === STATUS.PENDING}
- {...selectAllOptions}
- displaySelectAllCheckbox={displaySelectAllCheckbox}
+ rowSelectNodeFunc={rowSelectNodeFunc}
/>
)}
@@ -369,19 +306,20 @@ TableIndexPage.propTypes = {
controller: PropTypes.string,
creatable: PropTypes.bool,
customActionButtons: PropTypes.array,
- customActionKebabs: PropTypes.array,
customCreateAction: PropTypes.func,
customExportURL: PropTypes.string,
customHelpURL: PropTypes.string,
customSearchProps: PropTypes.object,
customToolbarItems: PropTypes.node,
+ response: PropTypes.object,
exportable: PropTypes.bool,
hasHelpPage: PropTypes.bool,
header: PropTypes.string,
isDeleteable: PropTypes.bool,
searchable: PropTypes.bool,
children: PropTypes.node,
- displaySelectAllCheckbox: PropTypes.bool,
+ selectionToolbar: PropTypes.node,
+ rowSelectNodeFunc: PropTypes.func,
};
TableIndexPage.defaultProps = {
@@ -391,9 +329,9 @@ TableIndexPage.defaultProps = {
columns: null,
children: null,
controller: '',
+ response: {},
creatable: true,
customActionButtons: [],
- customActionKebabs: [],
customCreateAction: null,
customExportURL: '',
customHelpURL: '',
@@ -404,7 +342,8 @@ TableIndexPage.defaultProps = {
header: '',
isDeleteable: false,
searchable: true,
- displaySelectAllCheckbox: false,
+ selectionToolbar: null,
+ rowSelectNodeFunc: noop,
};
export default TableIndexPage;
| |