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