Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Index Management] Keep the filters value in the url for the indices list #174515

Merged
merged 11 commits into from
Jan 18, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type TestSubjects =
| 'indexContextMenu'
| 'indexManagementHeaderContent'
| 'indexTable'
| 'indexTableIncludeHiddenIndicesToggle'
| 'checkboxToggles-includeHiddenIndices'
| 'indexTableIndexNameLink'
| 'indicesList'
| 'indicesTab'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const setup = async (httpSetup: HttpSetup): Promise<HomeTestBed> => {
};

const toggleHiddenIndices = async function () {
find('indexTableIncludeHiddenIndicesToggle').simulate('click');
find('checkboxToggles-includeHiddenIndices').simulate('click');
};

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const setup = async (

const clickIncludeHiddenIndicesToggle = () => {
const { find } = testBed;
find('indexTableIncludeHiddenIndicesToggle').simulate('click');
find('checkboxToggles-includeHiddenIndices').simulate('click');
};

const clickManageContextMenuButton = async () => {
Expand All @@ -88,7 +88,7 @@ export const setup = async (

const getIncludeHiddenIndicesToggleStatus = () => {
const { find } = testBed;
const props = find('indexTableIncludeHiddenIndicesToggle').props();
const props = find('checkboxToggles-includeHiddenIndices').props();
return Boolean(props['aria-checked']);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -650,11 +650,31 @@ describe('<IndexDetailsPage />', () => {
});
});

it('navigates back to indices', async () => {
jest.spyOn(testBed.routerMock.history, 'push');
await testBed.actions.clickBackToIndicesButton();
expect(testBed.routerMock.history.push).toHaveBeenCalledTimes(1);
expect(testBed.routerMock.history.push).toHaveBeenCalledWith('/indices');
describe('navigates back to the indices list', () => {
it('without indices list params', async () => {
jest.spyOn(testBed.routerMock.history, 'push');
await testBed.actions.clickBackToIndicesButton();
expect(testBed.routerMock.history.push).toHaveBeenCalledTimes(1);
expect(testBed.routerMock.history.push).toHaveBeenCalledWith('/indices');
});
it('with indices list params', async () => {
const filter = 'isFollower:true';
await act(async () => {
testBed = await setup({
httpSetup,
initialEntry: `/indices/index_details?indexName=${testIndexName}&filter=${encodeURIComponent(
filter
)}&includeHiddenIndices=true`,
});
});
testBed.component.update();
jest.spyOn(testBed.routerMock.history, 'push');
await testBed.actions.clickBackToIndicesButton();
expect(testBed.routerMock.history.push).toHaveBeenCalledTimes(1);
expect(testBed.routerMock.history.push).toHaveBeenCalledWith(
`/indices?filter=${encodeURIComponent(filter)}&includeHiddenIndices=true`
);
});
});

it('renders a link to discover', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ describe('index table', () => {
snapshot(indicesInTable);

// Enable "Show hidden indices"
const switchControl = findTestSubject(rendered, 'indexTableIncludeHiddenIndicesToggle');
const switchControl = findTestSubject(rendered, 'checkboxToggles-includeHiddenIndices');
switchControl.simulate('click');

// We do expect now the `.admin1` and `.admin3` indices to be in the list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import React, { useCallback, useEffect, useMemo, useState, FunctionComponent } from 'react';
import qs from 'query-string';
import { RouteComponentProps } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiPageTemplate, EuiText, EuiCode } from '@elastic/eui';
Expand Down Expand Up @@ -34,8 +35,12 @@ export const DetailsPage: FunctionComponent<
const [index, setIndex] = useState<Index | null>();

const navigateToIndicesList = useCallback(() => {
history.push(`/${Section.Indices}`);
}, [history]);
const indicesListParams = qs.parse(search);
delete indicesListParams.indexName;
delete indicesListParams.tab;
const paramsString = qs.stringify(indicesListParams);
history.push(`/${Section.Indices}${paramsString ? '?' : ''}${paramsString}`);
}, [history, search]);

const fetchIndexDetails = useCallback(async () => {
if (indexName) {
Expand Down Expand Up @@ -109,6 +114,7 @@ export const DetailsPage: FunctionComponent<
tab={tab}
fetchIndexDetails={fetchIndexDetails}
history={history}
search={search}
navigateToIndicesList={navigateToIndicesList}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ interface Props {
index: Index;
tab: IndexDetailsTabId;
history: RouteComponentProps['history'];
search: string;
fetchIndexDetails: () => Promise<void>;
navigateToIndicesList: () => void;
}
export const DetailsPageContent: FunctionComponent<Props> = ({
index,
tab,
history,
search,
fetchIndexDetails,
navigateToIndicesList,
}) => {
Expand Down Expand Up @@ -111,9 +113,9 @@ export const DetailsPageContent: FunctionComponent<Props> = ({

const onSectionChange = useCallback(
(newSection: IndexDetailsTabId) => {
return history.push(getIndexDetailsLink(index.name, newSection));
return history.push(getIndexDetailsLink(index.name, search, newSection));
},
[history, index]
[history, index.name, search]
);

const headerTabs = useMemo<EuiPageHeaderProps['tabs']>(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const AliasesDetails: FunctionComponent<{ aliases: Index['aliases'] }> =
}
const aliasesBadges = aliases.slice(0, MAX_VISIBLE_ALIASES).map((alias) => (
<EuiBadge
key={alias}
css={css`
max-width: 250px;
`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export class IndexActionsContextMenu extends Component {
indices,
reloadIndices,
unfreezeIndices,
indicesListURLParams,
} = this.props;
const allOpen = every(indexNames, (indexName) => {
return indexStatusByName[indexName] === INDEX_OPEN;
Expand All @@ -82,7 +83,9 @@ export class IndexActionsContextMenu extends Component {
defaultMessage: 'Show index overview',
}),
onClick: () => {
history.push(getIndexDetailsLink(indexNames[0], IndexDetailsSection.Overview));
history.push(
getIndexDetailsLink(indexNames[0], indicesListURLParams, IndexDetailsSection.Overview)
);
},
});
items.push({
Expand All @@ -91,7 +94,9 @@ export class IndexActionsContextMenu extends Component {
defaultMessage: 'Show index settings',
}),
onClick: () => {
history.push(getIndexDetailsLink(indexNames[0], IndexDetailsSection.Settings));
history.push(
getIndexDetailsLink(indexNames[0], indicesListURLParams, IndexDetailsSection.Settings)
);
},
});
items.push({
Expand All @@ -100,7 +105,9 @@ export class IndexActionsContextMenu extends Component {
defaultMessage: 'Show index mapping',
}),
onClick: () => {
history.push(getIndexDetailsLink(indexNames[0], IndexDetailsSection.Mappings));
history.push(
getIndexDetailsLink(indexNames[0], indicesListURLParams, IndexDetailsSection.Mappings)
);
},
});
if (allOpen && enableIndexActions) {
Expand All @@ -110,7 +117,9 @@ export class IndexActionsContextMenu extends Component {
defaultMessage: 'Show index stats',
}),
onClick: () => {
history.push(getIndexDetailsLink(indexNames[0], IndexDetailsSection.Stats));
history.push(
getIndexDetailsLink(indexNames[0], indicesListURLParams, IndexDetailsSection.Stats)
);
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import { NoMatch, DataHealth } from '../../../../components';
import { IndexActionsContextMenu } from '../index_actions_context_menu';
import { CreateIndexButton } from '../create_index/create_index_button';

const PAGE_SIZE_OPTIONS = [10, 50, 100];

const getHeaders = ({ showIndexStats }) => {
const headers = {};

Expand Down Expand Up @@ -118,18 +120,32 @@ export class IndexTable extends Component {

componentDidMount() {
this.props.loadIndices();
const { location, filterChanged } = this.props;
const { filter } = qs.parse((location && location.search) || '');
if (filter) {
const decodedFilter = attemptToURIDecode(filter);

const { filterChanged, pageSizeChanged, pageChanged, toggleNameToVisibleMap, toggleChanged } =
this.props;
const { filter, pageSize, pageIndex, ...rest } = this.readURLParams();

if (filter) {
try {
const filter = EuiSearchBar.Query.parse(decodedFilter);
filterChanged(filter);
const parsedFilter = EuiSearchBar.Query.parse(filter);
filterChanged(parsedFilter);
} catch (e) {
this.setState({ filterError: e });
}
}
if (pageSize && PAGE_SIZE_OPTIONS.includes(pageSize)) {
pageSizeChanged(pageSize);
}
if (pageIndex && pageIndex > -1) {
pageChanged(pageIndex);
}
const toggleParams = Object.keys(rest);
const toggles = Object.keys(toggleNameToVisibleMap);
for (const toggleParam of toggleParams) {
if (toggles.includes(toggleParam)) {
toggleChanged(toggleParam, rest[toggleParam] === 'true');
}
}
}

componentWillUnmount() {
Expand All @@ -142,21 +158,25 @@ export class IndexTable extends Component {

readURLParams() {
const { location } = this.props;
const { includeHiddenIndices } = qs.parse((location && location.search) || '');
const { filter, pageSize, pageIndex, ...rest } = qs.parse((location && location.search) || '');
return {
includeHiddenIndices: includeHiddenIndices === 'true',
filter: filter ? attemptToURIDecode(String(filter)) : undefined,
pageSize: pageSize ? Number(String(pageSize)) : undefined,
pageIndex: pageIndex ? Number(String(pageIndex)) : undefined,
...rest,
};
}

setIncludeHiddenParam(hidden) {
const { pathname, search } = this.props.location;
setURLParam(paramName, value) {
const { location, history } = this.props;
const { pathname, search } = location;
const params = qs.parse(search);
if (hidden) {
params.includeHiddenIndices = 'true';
if (value) {
params[paramName] = value;
} else {
delete params.includeHiddenIndices;
delete params[paramName];
}
this.props.history.push(pathname + '?' + qs.stringify(params));
history.push(pathname + '?' + qs.stringify(params));
}

onSort = (column) => {
Expand Down Expand Up @@ -196,6 +216,7 @@ export class IndexTable extends Component {
if (error) {
this.setState({ filterError: error });
} else {
this.setURLParam('filter', encodeURIComponent(query.text));
this.props.filterChanged(query);
this.setState({ filterError: null });
}
Expand Down Expand Up @@ -271,7 +292,7 @@ export class IndexTable extends Component {
}

buildRowCell(fieldName, value, index, appServices) {
const { filterChanged, history } = this.props;
const { filterChanged, history, location } = this.props;

if (fieldName === 'health') {
return <DataHealth health={value} />;
Expand All @@ -280,7 +301,7 @@ export class IndexTable extends Component {
<Fragment>
<EuiLink
data-test-subj="indexTableIndexNameLink"
onClick={() => history.push(getIndexDetailsLink(value))}
onClick={() => history.push(getIndexDetailsLink(value, location.search || ''))}
>
{value}
</EuiLink>
Expand Down Expand Up @@ -405,10 +426,16 @@ export class IndexTable extends Component {
<EuiTablePagination
activePage={pager.getCurrentPageIndex()}
itemsPerPage={pager.itemsPerPage}
itemsPerPageOptions={[10, 50, 100]}
itemsPerPageOptions={PAGE_SIZE_OPTIONS}
pageCount={pager.getTotalPages()}
onChangeItemsPerPage={pageSizeChanged}
onChangePage={pageChanged}
onChangeItemsPerPage={(pageSize) => {
this.setURLParam('pageSize', pageSize);
pageSizeChanged(pageSize);
}}
onChangePage={(pageIndex) => {
this.setURLParam('pageIndex', pageIndex);
pageChanged(pageIndex);
}}
/>
);
}
Expand All @@ -425,7 +452,10 @@ export class IndexTable extends Component {
id={`checkboxToggles-${name}`}
data-test-subj={`checkboxToggles-${name}`}
checked={toggleNameToVisibleMap[name]}
onChange={(event) => toggleChanged(name, event.target.checked)}
onChange={(event) => {
this.setURLParam(name, event.target.checked);
toggleChanged(name, event.target.checked);
}}
label={label}
/>
</EuiFlexItem>
Expand All @@ -442,9 +472,9 @@ export class IndexTable extends Component {
indicesError,
allIndices,
pager,
location,
} = this.props;

const { includeHiddenIndices } = this.readURLParams();
const hasContent = !indicesLoading && !indicesError;

if (!hasContent) {
Expand Down Expand Up @@ -530,21 +560,6 @@ export class IndexTable extends Component {
{extensionsService.toggles.map((toggle) => {
return this.renderToggleControl(toggle);
})}

<EuiFlexItem grow={false}>
<EuiSwitch
id="checkboxShowHiddenIndices"
data-test-subj="indexTableIncludeHiddenIndicesToggle"
checked={includeHiddenIndices}
onChange={(event) => this.setIncludeHiddenParam(event.target.checked)}
label={
<FormattedMessage
id="xpack.idxMgmt.indexTable.hiddenIndicesSwitchLabel"
defaultMessage="Include hidden indices"
/>
}
/>
</EuiFlexItem>
</EuiFlexGroup>
)}
</EuiFlexItem>
Expand All @@ -563,6 +578,7 @@ export class IndexTable extends Component {
<IndexActionsContextMenu
indexNames={Object.keys(selectedIndicesMap)}
isOnListView={true}
indicesListURLParams={location.search || ''}
resetSelection={() => {
this.setState({ selectedIndicesMap: {} });
}}
Expand Down
Loading