-
Notifications
You must be signed in to change notification settings - Fork 993
Commit
Update the TableIndexPage as a part of this action to accept things like select all Refs #36822 - Added a new change concent source action
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import React from 'react'; | ||
import { CubeIcon } from '@patternfly/react-icons'; | ||
import { translate as __ } from '../../common/I18n'; | ||
import TableIndexPage from '../PF4/TableIndexPage/TableIndexPage'; | ||
import { HOSTS_API_PATH, API_REQUEST_KEY } from '../../routes/Hosts/constants'; | ||
|
||
const HostsIndex = () => { | ||
const columns = { | ||
name: { | ||
title: __('Name'), | ||
wrapper: ({ can_edit: canEdit, id, name }) => | ||
canEdit ? ( | ||
<a href={`/models/${id}/edit`}>{name}</a> | ||
) : ( | ||
<span>{name}</span> | ||
), | ||
isSorted: true, | ||
}, | ||
}; | ||
|
||
const computeContentSource = search => | ||
`/change_host_content_source?search=${search}`; | ||
|
||
const customActionKebabs = [ | ||
{ | ||
title: __('Change content source'), | ||
icon: <CubeIcon />, | ||
computeHref: computeContentSource, | ||
}, | ||
]; | ||
|
||
return ( | ||
<TableIndexPage | ||
apiUrl={HOSTS_API_PATH} | ||
apiOptions={{ key: API_REQUEST_KEY }} | ||
header={__('Hosts')} | ||
controller="hosts" | ||
isDeleteable | ||
columns={columns} | ||
displaySelectAllCheckbox | ||
customActionKebabs={customActionKebabs} | ||
creatable={false} | ||
/> | ||
); | ||
}; | ||
|
||
export default HostsIndex; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React, { useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
Button, | ||
Check failure on line 4 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/ActionKebab.js GitHub Actions / test (12)
|
||
Dropdown, | ||
KebabToggle, | ||
DropdownItem, | ||
} from '@patternfly/react-core'; | ||
|
||
/** | ||
* Generate a button or a dropdown of buttons | ||
* @param {String} title The title of the button for the title and text inside the button | ||
* @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]; | ||
const [isOpen, setIsOpen] = useState(false); | ||
if (!items.length) return null; | ||
return ( | ||
<> | ||
{items.length > 0 && ( | ||
<Dropdown | ||
ouiaId="action-buttons-dropdown" | ||
toggle={ | ||
<KebabToggle | ||
aria-label="toggle action dropdown" | ||
onToggle={setIsOpen} | ||
/> | ||
} | ||
isOpen={isOpen} | ||
isPlain | ||
dropdownItems={items.map(item => ( | ||
<DropdownItem | ||
ouiaId={`${item.title}-dropdown-item`} | ||
key={item.title} | ||
title={item.title} | ||
{...item.action} | ||
isDisabled={item.isDisabled} | ||
> | ||
{item.icon} {item.title} | ||
</DropdownItem> | ||
))} | ||
/> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
ActionKebab.propTypes = { | ||
items: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
action: PropTypes.object, | ||
title: PropTypes.string, | ||
icon: PropTypes.node, | ||
isDisabled: PropTypes.bool, | ||
}) | ||
), | ||
}; | ||
|
||
ActionKebab.defaultProps = { | ||
items: [], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
Dropdown, | ||
DropdownToggle, | ||
DropdownToggleCheckbox, | ||
DropdownItem, | ||
} from '@patternfly/react-core'; | ||
import { translate as __ } from 'foremanReact/common/I18n'; | ||
Check failure on line 9 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
Check failure on line 9 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
Check failure on line 9 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (14)
|
||
import { noop } from 'foremanReact/common/helpers'; | ||
Check failure on line 10 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
Check failure on line 10 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
Check failure on line 10 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (14)
|
||
|
||
import './SelectAllCheckbox.scss'; | ||
|
||
const SelectAllCheckbox = ({ | ||
selectNone, | ||
selectPage, | ||
selectedCount, | ||
pageRowCount, | ||
totalCount, | ||
areAllRowsOnPageSelected, | ||
areAllRowsSelected, | ||
selectAll, | ||
}) => { | ||
const [isSelectAllDropdownOpen, setSelectAllDropdownOpen] = useState(false); | ||
const [selectionToggle, setSelectionToggle] = useState(false); | ||
|
||
const canSelectAll = selectAll !== noop; | ||
// Checkbox states: false = unchecked, null = partially-checked, true = checked | ||
// Flow: All are selected -> click -> none are selected | ||
// Some are selected -> click -> none are selected | ||
// None are selected -> click -> page is selected | ||
const onSelectAllCheckboxChange = checked => { | ||
if (checked && selectionToggle !== null) { | ||
if (!canSelectAll) { | ||
selectPage(); | ||
} else { | ||
selectAll(true); | ||
} | ||
} else { | ||
selectNone(); | ||
} | ||
}; | ||
|
||
const onSelectAllDropdownToggle = () => | ||
setSelectAllDropdownOpen(isOpen => !isOpen); | ||
|
||
const handleSelectAll = () => { | ||
setSelectAllDropdownOpen(false); | ||
setSelectionToggle(true); | ||
selectAll(true); | ||
}; | ||
const handleSelectPage = () => { | ||
setSelectAllDropdownOpen(false); | ||
setSelectionToggle(true); | ||
selectPage(); | ||
}; | ||
const handleSelectNone = () => { | ||
setSelectAllDropdownOpen(false); | ||
setSelectionToggle(false); | ||
selectNone(); | ||
}; | ||
|
||
useEffect(() => { | ||
let newCheckedState = null; // null is partially-checked state | ||
|
||
if (areAllRowsSelected) { | ||
newCheckedState = true; | ||
} else if (selectedCount === 0) { | ||
newCheckedState = false; | ||
} | ||
setSelectionToggle(newCheckedState); | ||
}, [selectedCount, areAllRowsSelected]); | ||
|
||
const selectAllDropdownItems = [ | ||
<DropdownItem | ||
key="select-none" | ||
ouiaId="select-none" | ||
component="button" | ||
isDisabled={selectedCount === 0} | ||
onClick={handleSelectNone} | ||
> | ||
{`${__('Select none')} (0)`} | ||
</DropdownItem>, | ||
<DropdownItem | ||
key="select-page" | ||
ouiaId="select-page" | ||
component="button" | ||
isDisabled={pageRowCount === 0 || areAllRowsOnPageSelected} | ||
onClick={handleSelectPage} | ||
> | ||
{`${__('Select page')} (${pageRowCount})`} | ||
</DropdownItem>, | ||
]; | ||
if (canSelectAll) { | ||
selectAllDropdownItems.push( | ||
<DropdownItem | ||
key="select-all" | ||
id="all" | ||
ouiaId="select-all" | ||
component="button" | ||
isDisabled={totalCount === 0 || areAllRowsSelected} | ||
onClick={handleSelectAll} | ||
> | ||
{`${__('Select all')} (${totalCount})`} | ||
</DropdownItem> | ||
); | ||
} | ||
|
||
return ( | ||
<Dropdown | ||
toggle={ | ||
<DropdownToggle | ||
onToggle={onSelectAllDropdownToggle} | ||
id="select-all-checkbox-dropdown-toggle" | ||
ouiaId="select-all-checkbox-dropdown-toggle" | ||
splitButtonItems={[ | ||
<DropdownToggleCheckbox | ||
className="tablewrapper-select-all-checkbox" | ||
key="tablewrapper-select-all-checkbox" | ||
ouiaId="select-all-checkbox-dropdown-toggle-checkbox" | ||
aria-label="Select all" | ||
onChange={checked => onSelectAllCheckboxChange(checked)} | ||
isChecked={selectionToggle} | ||
isDisabled={totalCount === 0 && selectedCount === 0} | ||
> | ||
{selectedCount > 0 && `${selectedCount} selected`} | ||
</DropdownToggleCheckbox>, | ||
]} | ||
/> | ||
} | ||
isOpen={isSelectAllDropdownOpen} | ||
dropdownItems={selectAllDropdownItems} | ||
id="selection-checkbox" | ||
ouiaId="selection-checkbox" | ||
/> | ||
); | ||
}; | ||
|
||
SelectAllCheckbox.propTypes = { | ||
selectedCount: PropTypes.number.isRequired, | ||
selectNone: PropTypes.func.isRequired, | ||
selectPage: PropTypes.func.isRequired, | ||
selectAll: PropTypes.func, | ||
pageRowCount: PropTypes.number.isRequired, | ||
totalCount: PropTypes.number.isRequired, | ||
areAllRowsOnPageSelected: PropTypes.bool.isRequired, | ||
areAllRowsSelected: PropTypes.bool.isRequired, | ||
}; | ||
|
||
SelectAllCheckbox.defaultProps = { | ||
selectAll: noop, | ||
pageRowCount: 0, | ||
Check failure on line 152 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
|
||
totalCount: 0, | ||
Check failure on line 153 in webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/SelectAllCheckbox.js GitHub Actions / test (12)
|
||
}; | ||
|
||
export default SelectAllCheckbox; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.tablewrapper-select-all-checkbox { | ||
font-weight: normal; | ||
} |