mirror of
https://github.com/ansible/awx.git
synced 2026-03-13 15:09:32 -02:30
clear list selection on navigate (first batch)
This commit is contained in:
@@ -37,7 +37,6 @@ function DataListToolbar({
|
||||
onExpand,
|
||||
onSelectAll,
|
||||
additionalControls,
|
||||
|
||||
qsConfig,
|
||||
pagination,
|
||||
}) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
|
||||
@@ -13,7 +13,7 @@ import useRequest, {
|
||||
useDismissableError,
|
||||
} from '../../util/useRequest';
|
||||
import { useConfig } from '../../contexts/Config';
|
||||
|
||||
import useSelected from '../../util/useSelected';
|
||||
import { isJobRunning, getJobModel } from '../../util/jobs';
|
||||
import { getQSConfig, parseQueryString } from '../../util/qs';
|
||||
import JobListItem from './JobListItem';
|
||||
@@ -35,8 +35,6 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
);
|
||||
|
||||
const { me } = useConfig();
|
||||
|
||||
const [selected, setSelected] = useState([]);
|
||||
const location = useLocation();
|
||||
const {
|
||||
result: { results, count, relatedSearchableKeys, searchableKeys },
|
||||
@@ -88,7 +86,14 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
|
||||
const jobs = useWsJobs(results, fetchJobsById, qsConfig);
|
||||
|
||||
const isAllSelected = selected.length === jobs.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
setSelected,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(jobs);
|
||||
|
||||
const {
|
||||
error: cancelJobsError,
|
||||
@@ -143,18 +148,6 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
setSelected([]);
|
||||
};
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...jobs] : []);
|
||||
};
|
||||
|
||||
const handleSelect = item => {
|
||||
if (selected.some(s => s.id === item.id)) {
|
||||
setSelected(selected.filter(s => s.id !== item.id));
|
||||
} else {
|
||||
setSelected(selected.concat(item));
|
||||
}
|
||||
};
|
||||
|
||||
const cannotDeleteItems = selected.filter(job => isJobRunning(job.status));
|
||||
|
||||
return (
|
||||
@@ -226,6 +219,7 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
renderToolbar={props => (
|
||||
@@ -233,7 +227,7 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={qsConfig}
|
||||
additionalControls={[
|
||||
<ToolbarDeleteButton
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'styled-components/macro';
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TableComposable, Tbody } from '@patternfly/react-table';
|
||||
|
||||
@@ -33,10 +33,16 @@ function PaginatedTable({
|
||||
showPageSizeOptions,
|
||||
renderToolbar,
|
||||
emptyContentMessage,
|
||||
clearSelected,
|
||||
ouiaId,
|
||||
}) {
|
||||
const { search, pathname } = useLocation();
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
clearSelected();
|
||||
}, [location.search, clearSelected]);
|
||||
|
||||
const pushHistoryState = qs => {
|
||||
history.push(qs ? `${pathname}?${qs}` : pathname);
|
||||
@@ -127,7 +133,7 @@ function PaginatedTable({
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<ListHeader
|
||||
itemCount={itemCount}
|
||||
renderToolbar={renderToolbar}
|
||||
@@ -159,7 +165,7 @@ function PaginatedTable({
|
||||
onPerPageSelect={handleSetPageSize}
|
||||
/>
|
||||
) : null}
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,6 +188,7 @@ PaginatedTable.propTypes = {
|
||||
renderToolbar: PropTypes.func,
|
||||
hasContentLoading: PropTypes.bool,
|
||||
contentError: PropTypes.shape(),
|
||||
clearSelected: PropTypes.func,
|
||||
ouiaId: PropTypes.string,
|
||||
};
|
||||
|
||||
@@ -195,6 +202,7 @@ PaginatedTable.defaultProps = {
|
||||
showPageSizeOptions: true,
|
||||
renderToolbar: props => <DataListToolbar {...props} />,
|
||||
ouiaId: null,
|
||||
clearSelected: () => {},
|
||||
};
|
||||
|
||||
export { PaginatedTable as _PaginatedTable };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { bool, func } from 'prop-types';
|
||||
|
||||
@@ -10,6 +10,7 @@ import PaginatedTable, { HeaderRow, HeaderCell } from '../../PaginatedTable';
|
||||
import DataListToolbar from '../../DataListToolbar';
|
||||
import { ToolbarAddButton, ToolbarDeleteButton } from '../../PaginatedDataList';
|
||||
import useRequest, { useDeleteItems } from '../../../util/useRequest';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
||||
import ScheduleListItem from './ScheduleListItem';
|
||||
|
||||
@@ -27,8 +28,6 @@ function ScheduleList({
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
}) {
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
const {
|
||||
@@ -76,8 +75,13 @@ function ScheduleList({
|
||||
fetchSchedules();
|
||||
}, [fetchSchedules]);
|
||||
|
||||
const isAllSelected =
|
||||
selected.length === schedules.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(schedules);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
@@ -95,21 +99,9 @@ function ScheduleList({
|
||||
}
|
||||
);
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...schedules] : []);
|
||||
};
|
||||
|
||||
const handleSelect = row => {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
await deleteJobs();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const canAdd =
|
||||
@@ -183,6 +175,7 @@ function ScheduleList({
|
||||
isMissingSurvey={isTemplate && hasMissingSurveyValue(item)}
|
||||
/>
|
||||
)}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -209,7 +202,7 @@ function ScheduleList({
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment, useEffect, useState, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation, Link } from 'react-router-dom';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
import { Card, DropdownItem } from '@patternfly/react-core';
|
||||
@@ -13,6 +13,7 @@ import ErrorDetail from '../ErrorDetail';
|
||||
import { ToolbarDeleteButton } from '../PaginatedDataList';
|
||||
import PaginatedTable, { HeaderRow, HeaderCell } from '../PaginatedTable';
|
||||
import useRequest, { useDeleteItems } from '../../util/useRequest';
|
||||
import useSelected from '../../util/useSelected';
|
||||
import { getQSConfig, parseQueryString } from '../../util/qs';
|
||||
import useWsTemplates from '../../util/useWsTemplates';
|
||||
import AddDropDownButton from '../AddDropDownButton';
|
||||
@@ -35,8 +36,6 @@ function TemplateList({ defaultParams }) {
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const {
|
||||
result: {
|
||||
results,
|
||||
@@ -87,8 +86,14 @@ function TemplateList({ defaultParams }) {
|
||||
|
||||
const templates = useWsTemplates(results);
|
||||
|
||||
const isAllSelected =
|
||||
selected.length === templates.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(templates);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteTemplates,
|
||||
@@ -117,19 +122,7 @@ function TemplateList({ defaultParams }) {
|
||||
|
||||
const handleTemplateDelete = async () => {
|
||||
await deleteTemplates();
|
||||
setSelected([]);
|
||||
};
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...templates] : []);
|
||||
};
|
||||
|
||||
const handleSelect = template => {
|
||||
if (selected.some(s => s.id === template.id)) {
|
||||
setSelected(selected.filter(s => s.id !== template.id));
|
||||
} else {
|
||||
setSelected(selected.concat(template));
|
||||
}
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const canAddJT =
|
||||
@@ -179,7 +172,7 @@ function TemplateList({ defaultParams }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
@@ -188,7 +181,7 @@ function TemplateList({ defaultParams }) {
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Templates`}
|
||||
qsConfig={qsConfig}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -235,7 +228,7 @@ function TemplateList({ defaultParams }) {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={qsConfig}
|
||||
additionalControls={[
|
||||
...(canAddJT || canAddWFJT ? [addButton] : []),
|
||||
@@ -281,7 +274,7 @@ function TemplateList({ defaultParams }) {
|
||||
{t`Failed to delete one or more templates.`}
|
||||
<ErrorDetail error={deletionError} />
|
||||
</AlertModal>
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,9 +76,14 @@ function CredentialList() {
|
||||
fetchCredentials();
|
||||
}, [fetchCredentials]);
|
||||
|
||||
const { selected, isAllSelected, handleSelect, setSelected } = useSelected(
|
||||
credentials
|
||||
);
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
setSelected,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(credentials);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
@@ -115,7 +120,7 @@ function CredentialList() {
|
||||
items={credentials}
|
||||
itemCount={credentialCount}
|
||||
qsConfig={QS_CONFIG}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
@@ -160,9 +165,7 @@ function CredentialList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={isSelected =>
|
||||
setSelected(isSelected ? [...credentials] : [])
|
||||
}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
@@ -17,6 +17,7 @@ import PaginatedTable, {
|
||||
HeaderCell,
|
||||
} from '../../../components/PaginatedTable';
|
||||
import useRequest, { useDeleteItems } from '../../../util/useRequest';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import {
|
||||
encodeQueryString,
|
||||
getQSConfig,
|
||||
@@ -36,7 +37,6 @@ function HostList() {
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const match = useRouteMatch();
|
||||
const [selected, setSelected] = useState([]);
|
||||
const parsedQueryStrings = parseQueryString(QS_CONFIG, location.search);
|
||||
const nonDefaultSearchParams = {};
|
||||
|
||||
@@ -86,7 +86,14 @@ function HostList() {
|
||||
fetchHosts();
|
||||
}, [fetchHosts]);
|
||||
|
||||
const isAllSelected = selected.length === hosts.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(hosts);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteHosts,
|
||||
@@ -105,19 +112,7 @@ function HostList() {
|
||||
|
||||
const handleHostDelete = async () => {
|
||||
await deleteHosts();
|
||||
setSelected([]);
|
||||
};
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...hosts] : []);
|
||||
};
|
||||
|
||||
const handleSelect = host => {
|
||||
if (selected.some(h => h.id === host.id)) {
|
||||
setSelected(selected.filter(h => h.id !== host.id));
|
||||
} else {
|
||||
setSelected(selected.concat(host));
|
||||
}
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const handleSmartInventoryClick = () => {
|
||||
@@ -141,7 +136,7 @@ function HostList() {
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Hosts`}
|
||||
qsConfig={QS_CONFIG}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -175,7 +170,7 @@ function HostList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
ToolbarAddButton,
|
||||
ToolbarDeleteButton,
|
||||
} from '../../../components/PaginatedDataList';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import AdHocCommands from '../../../components/AdHocCommands/AdHocCommands';
|
||||
import InventoryHostItem from './InventoryHostItem';
|
||||
|
||||
@@ -25,7 +26,6 @@ const QS_CONFIG = getQSConfig('host', {
|
||||
});
|
||||
|
||||
function InventoryHostList() {
|
||||
const [selected, setSelected] = useState([]);
|
||||
const [isAdHocLaunchLoading, setIsAdHocLaunchLoading] = useState(false);
|
||||
const { id } = useParams();
|
||||
const { search } = useLocation();
|
||||
@@ -74,17 +74,14 @@ function InventoryHostList() {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...hosts] : []);
|
||||
};
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(hosts);
|
||||
|
||||
const handleSelect = row => {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
};
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteHosts,
|
||||
@@ -99,12 +96,11 @@ function InventoryHostList() {
|
||||
|
||||
const handleDeleteHosts = async () => {
|
||||
await deleteHosts();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const canAdd =
|
||||
actions && Object.prototype.hasOwnProperty.call(actions, 'POST');
|
||||
const isAllSelected = selected.length > 0 && selected.length === hosts.length;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -115,6 +111,7 @@ function InventoryHostList() {
|
||||
itemCount={hostCount}
|
||||
pluralizedItemName={t`Hosts`}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
headerRow={
|
||||
@@ -128,7 +125,7 @@ function InventoryHostList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useLocation, useRouteMatch, Link } from 'react-router-dom';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
import { Card, PageSection, DropdownItem } from '@patternfly/react-core';
|
||||
import { InventoriesAPI } from '../../../api';
|
||||
import useRequest, { useDeleteItems } from '../../../util/useRequest';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import AlertModal from '../../../components/AlertModal';
|
||||
import DatalistToolbar from '../../../components/DataListToolbar';
|
||||
import ErrorDetail from '../../../components/ErrorDetail';
|
||||
@@ -27,7 +28,6 @@ const QS_CONFIG = getQSConfig('inventory', {
|
||||
function InventoryList() {
|
||||
const location = useLocation();
|
||||
const match = useRouteMatch();
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const {
|
||||
result: {
|
||||
@@ -89,8 +89,14 @@ function InventoryList() {
|
||||
QS_CONFIG
|
||||
);
|
||||
|
||||
const isAllSelected =
|
||||
selected.length === inventories.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(inventories);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteInventories,
|
||||
@@ -107,26 +113,12 @@ function InventoryList() {
|
||||
|
||||
const handleInventoryDelete = async () => {
|
||||
await deleteInventories();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const hasContentLoading = isDeleteLoading || isLoading;
|
||||
const canAdd = actions && actions.POST;
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...inventories] : []);
|
||||
};
|
||||
|
||||
const handleSelect = row => {
|
||||
if (!row.pending_deletion) {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const deleteDetailsRequests = relatedResourceDeleteRequests.inventory(
|
||||
selected[0]
|
||||
);
|
||||
@@ -197,6 +189,7 @@ function InventoryList() {
|
||||
]}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
clearSelected={clearSelected}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
@@ -211,7 +204,7 @@ function InventoryList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd ? [addButton] : []),
|
||||
@@ -251,7 +244,11 @@ function InventoryList() {
|
||||
? `${match.url}/smart_inventory/${inventory.id}/details`
|
||||
: `${match.url}/inventory/${inventory.id}/details`
|
||||
}
|
||||
onSelect={() => handleSelect(inventory)}
|
||||
onSelect={() => {
|
||||
if (!inventory.pending_deletion) {
|
||||
handleSelect(inventory);
|
||||
}
|
||||
}}
|
||||
isSelected={selected.some(row => row.id === inventory.id)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -306,7 +306,7 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
label={t`HTTP Headers`}
|
||||
value={JSON.stringify(configuration.headers)}
|
||||
mode="json"
|
||||
rows="6"
|
||||
rows={6}
|
||||
dataCy="nt-detail-webhook-headers"
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation, useRouteMatch } from 'react-router-dom';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
@@ -17,6 +17,7 @@ import PaginatedTable, {
|
||||
HeaderCell,
|
||||
} from '../../../components/PaginatedTable';
|
||||
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import OrganizationListItem from './OrganizationListItem';
|
||||
import { relatedResourceDeleteRequests } from '../../../util/getRelatedResourceDeleteDetails';
|
||||
|
||||
@@ -30,8 +31,6 @@ function OrganizationsList() {
|
||||
const location = useLocation();
|
||||
const match = useRouteMatch();
|
||||
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const addUrl = `${match.url}/add`;
|
||||
|
||||
const {
|
||||
@@ -77,8 +76,14 @@ function OrganizationsList() {
|
||||
fetchOrganizations();
|
||||
}, [fetchOrganizations]);
|
||||
|
||||
const isAllSelected =
|
||||
selected.length === organizations.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(organizations);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteOrganizations,
|
||||
@@ -99,23 +104,12 @@ function OrganizationsList() {
|
||||
|
||||
const handleOrgDelete = async () => {
|
||||
await deleteOrganizations();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const hasContentLoading = isDeleteLoading || isOrgsLoading;
|
||||
const canAdd = actions && actions.POST;
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...organizations] : []);
|
||||
};
|
||||
|
||||
const handleSelect = row => {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
};
|
||||
const deleteDetailsRequests = relatedResourceDeleteRequests.organization(
|
||||
selected[0]
|
||||
);
|
||||
@@ -131,6 +125,7 @@ function OrganizationsList() {
|
||||
itemCount={organizationCount}
|
||||
pluralizedItemName={t`Organizations`}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -165,7 +160,7 @@ function OrganizationsList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation, useRouteMatch } from 'react-router-dom';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
@@ -17,6 +17,7 @@ import PaginatedTable, {
|
||||
HeaderCell,
|
||||
} from '../../../components/PaginatedTable';
|
||||
import useWsProjects from './useWsProjects';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import { relatedResourceDeleteRequests } from '../../../util/getRelatedResourceDeleteDetails';
|
||||
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
||||
|
||||
@@ -31,7 +32,6 @@ const QS_CONFIG = getQSConfig('project', {
|
||||
function ProjectList() {
|
||||
const location = useLocation();
|
||||
const match = useRouteMatch();
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const {
|
||||
result: {
|
||||
@@ -78,8 +78,15 @@ function ProjectList() {
|
||||
|
||||
const projects = useWsProjects(results);
|
||||
|
||||
const isAllSelected =
|
||||
selected.length === projects.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
setSelected,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(projects);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteProjects,
|
||||
@@ -104,24 +111,12 @@ function ProjectList() {
|
||||
const hasContentLoading = isDeleteLoading || isLoading;
|
||||
const canAdd = actions && actions.POST;
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...projects] : []);
|
||||
};
|
||||
|
||||
const handleSelect = row => {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
};
|
||||
|
||||
const deleteDetailsRequests = relatedResourceDeleteRequests.project(
|
||||
selected[0]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<PageSection>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
@@ -131,7 +126,7 @@ function ProjectList() {
|
||||
itemCount={itemCount}
|
||||
pluralizedItemName={t`Projects`}
|
||||
qsConfig={QS_CONFIG}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -182,7 +177,7 @@ function ProjectList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
@@ -239,7 +234,7 @@ function ProjectList() {
|
||||
{t`Failed to delete one or more projects.`}
|
||||
<ErrorDetail error={deletionError} />
|
||||
</AlertModal>
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { useLocation, useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
ToolbarAddButton,
|
||||
ToolbarDeleteButton,
|
||||
} from '../../../components/PaginatedDataList';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
||||
|
||||
import TeamListItem from './TeamListItem';
|
||||
@@ -30,7 +31,6 @@ const QS_CONFIG = getQSConfig('team', {
|
||||
function TeamList() {
|
||||
const location = useLocation();
|
||||
const match = useRouteMatch();
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const {
|
||||
result: {
|
||||
@@ -75,7 +75,14 @@ function TeamList() {
|
||||
fetchTeams();
|
||||
}, [fetchTeams]);
|
||||
|
||||
const isAllSelected = selected.length === teams.length && selected.length > 0;
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(teams);
|
||||
|
||||
const {
|
||||
isLoading: isDeleteLoading,
|
||||
deleteItems: deleteTeams,
|
||||
@@ -94,26 +101,14 @@ function TeamList() {
|
||||
|
||||
const handleTeamDelete = async () => {
|
||||
await deleteTeams();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const hasContentLoading = isDeleteLoading || isLoading;
|
||||
const canAdd = actions && actions.POST;
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...teams] : []);
|
||||
};
|
||||
|
||||
const handleSelect = row => {
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(selected.filter(s => s.id !== row.id));
|
||||
} else {
|
||||
setSelected(selected.concat(row));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<PageSection>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
@@ -123,7 +118,7 @@ function TeamList() {
|
||||
itemCount={itemCount}
|
||||
pluralizedItemName={t`Teams`}
|
||||
qsConfig={QS_CONFIG}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
@@ -161,7 +156,7 @@ function TeamList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
@@ -208,7 +203,7 @@ function TeamList() {
|
||||
{t`Failed to delete one or more teams.`}
|
||||
<ErrorDetail error={deletionError} />
|
||||
</AlertModal>
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { ToolbarAddButton } from '../../../components/PaginatedDataList';
|
||||
import SurveyListItem from './SurveyListItem';
|
||||
import SurveyToolbar from './SurveyToolbar';
|
||||
import SurveyPreviewModal from './SurveyPreviewModal';
|
||||
import useSelected from '../../../util/useSelected';
|
||||
|
||||
const Button = styled(_Button)`
|
||||
margin: 20px;
|
||||
@@ -36,15 +37,16 @@ function SurveyList({
|
||||
const match = useRouteMatch();
|
||||
|
||||
const questions = survey?.spec || [];
|
||||
const [selected, setSelected] = useState([]);
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [isPreviewModalOpen, setIsPreviewModalOpen] = useState(false);
|
||||
const isAllSelected =
|
||||
selected.length === questions?.length && selected.length > 0;
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...questions] : []);
|
||||
};
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
setSelected,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
} = useSelected(questions);
|
||||
|
||||
const handleSelect = item => {
|
||||
if (selected.some(q => q.variable === item.variable)) {
|
||||
@@ -61,7 +63,7 @@ function SurveyList({
|
||||
await updateSurvey(questions.filter(q => !selected.includes(q)));
|
||||
}
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const moveUp = question => {
|
||||
@@ -91,7 +93,7 @@ function SurveyList({
|
||||
isOpen={isDeleteModalOpen}
|
||||
onClose={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
}}
|
||||
actions={[
|
||||
<Button
|
||||
@@ -110,7 +112,7 @@ function SurveyList({
|
||||
aria-label={t`cancel delete`}
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
}}
|
||||
>
|
||||
{t`Cancel`}
|
||||
@@ -181,7 +183,7 @@ function SurveyList({
|
||||
<>
|
||||
<SurveyToolbar
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
onSelectAll={selectAll}
|
||||
surveyEnabled={surveyEnabled}
|
||||
onToggleSurvey={toggleSurvey}
|
||||
isDeleteDisabled={selected?.length === 0}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
/**
|
||||
* useSelected hook provides a way to read and update a selected list
|
||||
@@ -8,6 +8,7 @@ import { useState } from 'react';
|
||||
* isAllSelected: boolean that indicates if all items are selected
|
||||
* handleSelect: function that adds and removes items from selected list
|
||||
* setSelected: setter function
|
||||
* clearSelected: de-select all items
|
||||
* }
|
||||
*/
|
||||
|
||||
@@ -16,6 +17,9 @@ export default function useSelected(list = []) {
|
||||
const isAllSelected = selected.length > 0 && selected.length === list.length;
|
||||
|
||||
const handleSelect = row => {
|
||||
if (!row.id) {
|
||||
throw new Error(`Selected row does not have an id`);
|
||||
}
|
||||
if (selected.some(s => s.id === row.id)) {
|
||||
setSelected(prevState => [...prevState.filter(i => i.id !== row.id)]);
|
||||
} else {
|
||||
@@ -23,5 +27,23 @@ export default function useSelected(list = []) {
|
||||
}
|
||||
};
|
||||
|
||||
return { selected, isAllSelected, handleSelect, setSelected };
|
||||
const selectAll = useCallback(
|
||||
isSelected => {
|
||||
setSelected(isSelected ? [...list] : []);
|
||||
},
|
||||
[list]
|
||||
);
|
||||
|
||||
const clearSelected = useCallback(() => {
|
||||
setSelected([]);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
setSelected,
|
||||
selectAll,
|
||||
clearSelected,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user