mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Endpoint] Show Host Status on List view (#64455)
* show host status on list * Adjust type for HostStatus-to-HealthColor * Fixed unit tests * Tests * removed unused translation keys * clarify test case description * remove `ts-ignore`
This commit is contained in:
parent
231de27026
commit
97d7620fcc
8 changed files with 82 additions and 27 deletions
|
@ -57,7 +57,7 @@ describe('HostList store concerns', () => {
|
|||
});
|
||||
|
||||
const currentState = store.getState();
|
||||
expect(currentState.hosts).toEqual(payload.hosts.map(hostInfo => hostInfo.metadata));
|
||||
expect(currentState.hosts).toEqual(payload.hosts);
|
||||
expect(currentState.pageSize).toEqual(payload.request_page_size);
|
||||
expect(currentState.pageIndex).toEqual(payload.request_page_index);
|
||||
expect(currentState.total).toEqual(payload.total);
|
||||
|
|
|
@ -62,6 +62,6 @@ describe('host list middleware', () => {
|
|||
paging_properties: [{ page_index: '0' }, { page_size: '10' }],
|
||||
}),
|
||||
});
|
||||
expect(listData(getState())).toEqual(apiResponse.hosts.map(hostInfo => hostInfo.metadata));
|
||||
expect(listData(getState())).toEqual(apiResponse.hosts);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
|
|||
} = action.payload;
|
||||
return {
|
||||
...state,
|
||||
hosts: hosts.map(hostInfo => hostInfo.metadata),
|
||||
hosts,
|
||||
total,
|
||||
pageSize,
|
||||
pageIndex,
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
UIPolicyConfig,
|
||||
PolicyData,
|
||||
HostPolicyResponse,
|
||||
HostInfo,
|
||||
} from '../../../common/types';
|
||||
import { EndpointPluginStartDependencies } from '../../plugin';
|
||||
import { AppAction } from './store/action';
|
||||
|
@ -91,7 +92,7 @@ export type SubstateMiddlewareFactory = <Substate>(
|
|||
|
||||
export interface HostState {
|
||||
/** list of host **/
|
||||
hosts: HostMetadata[];
|
||||
hosts: HostInfo[];
|
||||
/** number of items per page */
|
||||
pageSize: number;
|
||||
/** which page to show */
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
mockHostResultList,
|
||||
} from '../../store/hosts/mock_host_result_list';
|
||||
import { AppContextTestRender, createAppRootMockRenderer } from '../../mocks';
|
||||
import { HostInfo, HostPolicyResponseActionStatus } from '../../../../../common/types';
|
||||
import { HostInfo, HostStatus, HostPolicyResponseActionStatus } from '../../../../../common/types';
|
||||
import { EndpointDocGenerator } from '../../../../../common/generate_data';
|
||||
|
||||
describe('when on the hosts page', () => {
|
||||
|
@ -48,21 +48,50 @@ describe('when on the hosts page', () => {
|
|||
describe('when list data loads', () => {
|
||||
beforeEach(() => {
|
||||
reactTestingLibrary.act(() => {
|
||||
const hostListData = mockHostResultList({ total: 3 });
|
||||
[HostStatus.ERROR, HostStatus.ONLINE, HostStatus.OFFLINE].forEach((status, index) => {
|
||||
hostListData.hosts[index] = {
|
||||
metadata: hostListData.hosts[index].metadata,
|
||||
host_status: status,
|
||||
};
|
||||
});
|
||||
const action: AppAction = {
|
||||
type: 'serverReturnedHostList',
|
||||
payload: mockHostResultList(),
|
||||
payload: hostListData,
|
||||
};
|
||||
store.dispatch(action);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render the host summary row in the table', async () => {
|
||||
it('should display rows in the table', async () => {
|
||||
const renderResult = render();
|
||||
const rows = await renderResult.findAllByRole('row');
|
||||
expect(rows).toHaveLength(2);
|
||||
expect(rows).toHaveLength(4);
|
||||
});
|
||||
it('should show total', async () => {
|
||||
const renderResult = render();
|
||||
const total = await renderResult.findByTestId('hostListTableTotal');
|
||||
expect(total.textContent).toEqual('3 Hosts');
|
||||
});
|
||||
it('should display correct status', async () => {
|
||||
const renderResult = render();
|
||||
const hostStatuses = await renderResult.findAllByTestId('rowHostStatus');
|
||||
|
||||
expect(hostStatuses[0].textContent).toEqual('Error');
|
||||
expect(hostStatuses[0].querySelector('[data-euiicon-type][color="danger"]')).not.toBeNull();
|
||||
|
||||
expect(hostStatuses[1].textContent).toEqual('Online');
|
||||
expect(
|
||||
hostStatuses[1].querySelector('[data-euiicon-type][color="success"]')
|
||||
).not.toBeNull();
|
||||
|
||||
expect(hostStatuses[2].textContent).toEqual('Offline');
|
||||
expect(
|
||||
hostStatuses[2].querySelector('[data-euiicon-type][color="subdued"]')
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('when the user clicks the hostname in the table', () => {
|
||||
describe('when the user clicks the first hostname in the table', () => {
|
||||
let renderResult: reactTestingLibrary.RenderResult;
|
||||
beforeEach(async () => {
|
||||
const hostDetailsApiResponse = mockHostDetailsApiResult();
|
||||
|
@ -76,9 +105,9 @@ describe('when on the hosts page', () => {
|
|||
});
|
||||
|
||||
renderResult = render();
|
||||
const detailsLink = await renderResult.findByTestId('hostnameCellLink');
|
||||
if (detailsLink) {
|
||||
reactTestingLibrary.fireEvent.click(detailsLink);
|
||||
const hostNameLinks = await renderResult.findAllByTestId('hostnameCellLink');
|
||||
if (hostNameLinks.length) {
|
||||
reactTestingLibrary.fireEvent.click(hostNameLinks[0]);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -16,10 +16,20 @@ import * as selectors from '../../store/hosts/selectors';
|
|||
import { useHostSelector } from './hooks';
|
||||
import { CreateStructuredSelector } from '../../types';
|
||||
import { urlFromQueryParams } from './url_from_query_params';
|
||||
import { HostMetadata, Immutable } from '../../../../../common/types';
|
||||
import { HostInfo, HostStatus, Immutable } from '../../../../../common/types';
|
||||
import { PageView } from '../components/page_view';
|
||||
import { useNavigateByRouterEventHandler } from '../hooks/use_navigate_by_router_event_handler';
|
||||
|
||||
const HOST_STATUS_TO_HEALTH_COLOR = Object.freeze<
|
||||
{
|
||||
[key in HostStatus]: string;
|
||||
}
|
||||
>({
|
||||
[HostStatus.ERROR]: 'danger',
|
||||
[HostStatus.ONLINE]: 'success',
|
||||
[HostStatus.OFFLINE]: 'subdued',
|
||||
});
|
||||
|
||||
const HostLink = memo<{
|
||||
name: string;
|
||||
href: string;
|
||||
|
@ -73,20 +83,40 @@ export const HostList = () => {
|
|||
[history, queryParams]
|
||||
);
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<Immutable<HostMetadata>>> = useMemo(() => {
|
||||
const columns: Array<EuiBasicTableColumn<Immutable<HostInfo>>> = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
field: '',
|
||||
field: 'metadata.host',
|
||||
name: i18n.translate('xpack.endpoint.host.list.hostname', {
|
||||
defaultMessage: 'Hostname',
|
||||
}),
|
||||
render: ({ host: { hostname, id } }: { host: { hostname: string; id: string } }) => {
|
||||
render: ({ hostname, id }: HostInfo['metadata']['host']) => {
|
||||
const newQueryParams = urlFromQueryParams({ ...queryParams, selected_host: id });
|
||||
return (
|
||||
<HostLink name={hostname} href={'?' + newQueryParams.search} route={newQueryParams} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'host_status',
|
||||
name: i18n.translate('xpack.endpoint.host.list.hostStatus', {
|
||||
defaultMessage: 'Host Status',
|
||||
}),
|
||||
render: (hostStatus: HostInfo['host_status']) => {
|
||||
return (
|
||||
<EuiHealth
|
||||
color={HOST_STATUS_TO_HEALTH_COLOR[hostStatus]}
|
||||
data-test-subj="rowHostStatus"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.endpoint.host.list.hostStatusValue"
|
||||
defaultMessage="{hostStatus, select, online {Online} error {Error} other {Offline}}"
|
||||
values={{ hostStatus }}
|
||||
/>
|
||||
</EuiHealth>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
name: i18n.translate('xpack.endpoint.host.list.policy', {
|
||||
|
@ -117,26 +147,23 @@ export const HostList = () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
field: 'host.os.name',
|
||||
field: 'metadata.host.os.name',
|
||||
name: i18n.translate('xpack.endpoint.host.list.os', {
|
||||
defaultMessage: 'Operating System',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'host.ip',
|
||||
field: 'metadata.host.ip',
|
||||
name: i18n.translate('xpack.endpoint.host.list.ip', {
|
||||
defaultMessage: 'IP Address',
|
||||
}),
|
||||
truncateText: true,
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
name: i18n.translate('xpack.endpoint.host.list.sensorVersion', {
|
||||
defaultMessage: 'Sensor Version',
|
||||
field: 'metadata.agent.version',
|
||||
name: i18n.translate('xpack.endpoint.host.list.endpointVersion', {
|
||||
defaultMessage: 'Version',
|
||||
}),
|
||||
render: () => {
|
||||
return 'version';
|
||||
},
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
|
@ -158,7 +185,7 @@ export const HostList = () => {
|
|||
headerLeft={i18n.translate('xpack.endpoint.host.hosts', { defaultMessage: 'Hosts' })}
|
||||
>
|
||||
{hasSelectedHost && <HostDetailsFlyout />}
|
||||
<EuiText color="subdued" size="xs">
|
||||
<EuiText color="subdued" size="xs" data-test-subj="hostListTableTotal">
|
||||
<FormattedMessage
|
||||
id="xpack.endpoint.host.list.totalCount"
|
||||
defaultMessage="{totalItemCount, plural, one {# Host} other {# Hosts}}"
|
||||
|
|
|
@ -6370,7 +6370,6 @@
|
|||
"xpack.endpoint.host.list.os": "オペレーティングシステム",
|
||||
"xpack.endpoint.host.list.policy": "ポリシー",
|
||||
"xpack.endpoint.host.list.policyStatus": "ポリシーステータス",
|
||||
"xpack.endpoint.host.list.sensorVersion": "サーバーバージョン",
|
||||
"xpack.endpoint.host.list.totalCount": "表示中: {totalItemCount, plural, one {# ホスト} other {# ホスト}}",
|
||||
"xpack.endpoint.notFound": "ページが見つかりません",
|
||||
"xpack.endpoint.pluginTitle": "エンドポイント",
|
||||
|
|
|
@ -6372,7 +6372,6 @@
|
|||
"xpack.endpoint.host.list.os": "操作系统",
|
||||
"xpack.endpoint.host.list.policy": "政策",
|
||||
"xpack.endpoint.host.list.policyStatus": "策略状态",
|
||||
"xpack.endpoint.host.list.sensorVersion": "感应器版本",
|
||||
"xpack.endpoint.host.list.totalCount": "正在显示:{totalItemCount, plural, one {# 个主机} other {# 个主机}}",
|
||||
"xpack.endpoint.notFound": "未找到页面",
|
||||
"xpack.endpoint.pluginTitle": "终端",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue