Skip to content

Commit

Permalink
[Ingest Manager] Add ability to sort to agent configs and package con…
Browse files Browse the repository at this point in the history
…figs (#70676)

* Add sorting params to list endpoints; allow sorting on agent config and package config tables; normalize casing of 'desc' and 'asc'

* Fix es archiver data

* Fix tests
  • Loading branch information
jen-huang authored Jul 3, 2020
1 parent 5226ea2 commit 54348a7
Show file tree
Hide file tree
Showing 16 changed files with 83 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
*/

export interface ListWithKuery {
page: number;
perPage: number;
page?: number;
perPage?: number;
sortField?: string;
sortOrder?: 'desc' | 'asc';
kuery?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export { useLink } from './use_link';
export { useKibanaLink } from './use_kibana_link';
export { usePackageIconType, UsePackageIconType } from './use_package_icon_type';
export { usePagination, Pagination } from './use_pagination';
export { useSorting } from './use_sorting';
export { useDebounce } from './use_debounce';
export * from './use_request';
export * from './use_input';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { useState } from 'react';
import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table';

export function useSorting<T>(defaultSorting: CriteriaWithPagination<T>['sort']) {
const [sorting, setSorting] = useState<CriteriaWithPagination<T>['sort']>(defaultSorting);

return {
sorting,
setSorting,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ export const StepSelectConfig: React.FunctionComponent<{
data: agentConfigsData,
error: agentConfigsError,
isLoading: isAgentConfigsLoading,
} = useGetAgentConfigs();
} = useGetAgentConfigs({
page: 1,
perPage: 1000,
sortField: 'name',
sortOrder: 'asc',
});
const agentConfigs = agentConfigsData?.items || [];
const agentConfigsById = agentConfigs.reduce(
(acc: { [key: string]: GetAgentConfigsResponseItem }, config) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const PackageConfigsTable: React.FunctionComponent<Props> = ({
(): EuiInMemoryTableProps<InMemoryPackageConfig>['columns'] => [
{
field: 'name',
sortable: true,
name: i18n.translate(
'xpack.ingestManager.configDetails.packageConfigsTable.nameColumnTitle',
{
Expand All @@ -137,6 +138,7 @@ export const PackageConfigsTable: React.FunctionComponent<Props> = ({
},
{
field: 'packageTitle',
sortable: true,
name: i18n.translate(
'xpack.ingestManager.configDetails.packageConfigsTable.packageNameColumnTitle',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
EuiTableFieldDataColumnType,
EuiTextColor,
} from '@elastic/eui';
import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, FormattedDate } from '@kbn/i18n/react';
import { useHistory } from 'react-router-dom';
Expand All @@ -27,6 +28,7 @@ import {
useCapabilities,
useGetAgentConfigs,
usePagination,
useSorting,
useLink,
useConfig,
useUrlParams,
Expand Down Expand Up @@ -84,6 +86,10 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
: urlParams.kuery ?? ''
);
const { pagination, pageSizeOptions, setPagination } = usePagination();
const { sorting, setSorting } = useSorting<AgentConfig>({
field: 'updated_at',
direction: 'desc',
});
const history = useHistory();
const isCreateAgentConfigFlyoutOpen = 'create' in urlParams;
const setIsCreateAgentConfigFlyoutOpen = useCallback(
Expand All @@ -106,6 +112,8 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
const { isLoading, data: agentConfigData, sendRequest } = useGetAgentConfigs({
page: pagination.currentPage,
perPage: pagination.pageSize,
sortField: sorting?.field,
sortOrder: sorting?.direction,
kuery: search,
});

Expand All @@ -116,6 +124,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
> = [
{
field: 'name',
sortable: true,
name: i18n.translate('xpack.ingestManager.agentConfigList.nameColumnTitle', {
defaultMessage: 'Name',
}),
Expand Down Expand Up @@ -158,6 +167,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
},
{
field: 'updated_at',
sortable: true,
name: i18n.translate('xpack.ingestManager.agentConfigList.updatedOnColumnTitle', {
defaultMessage: 'Last updated on',
}),
Expand Down Expand Up @@ -240,6 +250,16 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
[createAgentConfigButton]
);

const onTableChange = (criteria: CriteriaWithPagination<AgentConfig>) => {
const newPagination = {
...pagination,
currentPage: criteria.page.index + 1,
pageSize: criteria.page.size,
};
setPagination(newPagination);
setSorting(criteria.sort);
};

return (
<AgentConfigListPageLayout>
{isCreateAgentConfigFlyoutOpen ? (
Expand Down Expand Up @@ -276,7 +296,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
</EuiFlexGroup>

<EuiSpacer size="m" />
<EuiBasicTable
<EuiBasicTable<AgentConfig>
loading={isLoading}
hasActions={true}
noItemsMessage={
Expand Down Expand Up @@ -314,14 +334,8 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
totalItemCount: agentConfigData ? agentConfigData.total : 0,
pageSizeOptions,
}}
onChange={({ page }: { page: { index: number; size: number } }) => {
const newPagination = {
...pagination,
currentPage: page.index + 1,
pageSize: page.size,
};
setPagination(newPagination);
}}
sorting={{ sort: sorting }}
onChange={onTableChange}
/>
</AgentConfigListPageLayout>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const AgentReassignConfigFlyout: React.FunctionComponent<Props> = ({ onCl
agent.config_id
);

const agentConfigsRequest = useGetAgentConfigs();
const agentConfigsRequest = useGetAgentConfigs({
page: 1,
perPage: 1000,
});
const agentConfigs = agentConfigsRequest.data ? agentConfigsRequest.data.items : [];

const [isSubmitting, setIsSubmitting] = useState(false);
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/ingest_manager/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ const savedObjectTypes: { [key: string]: SavedObjectsType } = {
},
mappings: {
properties: {
id: { type: 'keyword' },
name: { type: 'text' },
name: { type: 'keyword' },
description: { type: 'text' },
namespace: { type: 'keyword' },
is_default: { type: 'boolean' },
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/ingest_manager/server/services/agent_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,12 @@ class AgentConfigService {
soClient: SavedObjectsClientContract,
options: ListWithKuery
): Promise<{ items: AgentConfig[]; total: number; page: number; perPage: number }> {
const { page = 1, perPage = 20, kuery } = options;
const { page = 1, perPage = 20, sortField = 'updated_at', sortOrder = 'desc', kuery } = options;

const agentConfigs = await soClient.find<AgentConfigSOAttributes>({
type: SAVED_OBJECT_TYPE,
sortField,
sortOrder,
page,
perPage,
// To ensure users don't need to know about SO data structure...
Expand Down Expand Up @@ -273,7 +275,6 @@ class AgentConfigService {
soClient,
id,
{
...oldAgentConfig,
package_configs: uniq(
[...((oldAgentConfig.package_configs || []) as string[])].filter(
(pkgConfigId) => !packageConfigIds.includes(pkgConfigId)
Expand Down
36 changes: 12 additions & 24 deletions x-pack/plugins/ingest_manager/server/services/agents/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,24 @@ import {
AGENT_TYPE_EPHEMERAL,
AGENT_POLLING_THRESHOLD_MS,
} from '../../constants';
import { AgentSOAttributes, Agent, AgentEventSOAttributes } from '../../types';
import { AgentSOAttributes, Agent, AgentEventSOAttributes, ListWithKuery } from '../../types';
import { savedObjectToAgent } from './saved_objects';
import { escapeSearchQueryPhrase } from '../saved_object';

export async function listAgents(
soClient: SavedObjectsClientContract,
options: {
page: number;
perPage: number;
kuery?: string;
options: ListWithKuery & {
showInactive: boolean;
}
) {
const { page, perPage, kuery, showInactive = false } = options;
const {
page = 1,
perPage = 20,
sortField = 'enrolled_at',
sortOrder = 'desc',
kuery,
showInactive = false,
} = options;

const filters = [];

Expand All @@ -49,10 +53,11 @@ export async function listAgents(

const { saved_objects, total } = await soClient.find<AgentSOAttributes>({
type: AGENT_SAVED_OBJECT_TYPE,
sortField,
sortOrder,
page,
perPage,
filter: _joinFilters(filters),
..._getSortFields(),
});

const agents: Agent[] = saved_objects.map(savedObjectToAgent);
Expand Down Expand Up @@ -137,23 +142,6 @@ export async function deleteAgent(soClient: SavedObjectsClientContract, agentId:
});
}

function _getSortFields(sortOption?: string) {
switch (sortOption) {
case 'ASC':
return {
sortField: 'enrolled_at',
sortOrder: 'ASC',
};

case 'DESC':
default:
return {
sortField: 'enrolled_at',
sortOrder: 'DESC',
};
}
}

function _joinFilters(filters: string[], operator = 'AND') {
return filters.reduce((acc: string | undefined, filter) => {
if (acc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function getAgentEvents(
perPage,
page,
sortField: 'timestamp',
sortOrder: 'DESC',
sortOrder: 'desc',
defaultSearchOperator: 'AND',
search: agentId,
searchFields: ['agent_id'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async function getEventsCount(soClient: SavedObjectsClientContract, configId?: s
perPage: 0,
page: 1,
sortField: 'timestamp',
sortOrder: 'DESC',
sortOrder: 'desc',
defaultSearchOperator: 'AND',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function listEnrollmentApiKeys(
page,
perPage,
sortField: 'created_at',
sortOrder: 'DESC',
sortOrder: 'desc',
filter:
kuery && kuery !== ''
? kuery.replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ class PackageConfigService {
soClient: SavedObjectsClientContract,
options: ListWithKuery
): Promise<{ items: PackageConfig[]; total: number; page: number; perPage: number }> {
const { page = 1, perPage = 20, kuery } = options;
const { page = 1, perPage = 20, sortField = 'updated_at', sortOrder = 'desc', kuery } = options;

const packageConfigs = await soClient.find<PackageConfigSOAttributes>({
type: SAVED_OBJECT_TYPE,
sortField,
sortOrder,
page,
perPage,
// To ensure users don't need to know about SO data structure...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import { schema, TypeOf } from '@kbn/config-schema';

export const ListWithKuerySchema = schema.object({
page: schema.number({ defaultValue: 1 }),
perPage: schema.number({ defaultValue: 20 }),
page: schema.maybe(schema.number({ defaultValue: 1 })),
perPage: schema.maybe(schema.number({ defaultValue: 20 })),
sortField: schema.maybe(schema.string()),
sortOrder: schema.maybe(schema.oneOf([schema.literal('desc'), schema.literal('asc')])),
kuery: schema.maybe(schema.string()),
});

Expand Down
3 changes: 1 addition & 2 deletions x-pack/test/functional/es_archives/fleet/agents/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,7 @@
],
"revision": 2,
"updated_at": "2020-05-07T19:34:42.533Z",
"updated_by": "system",
"id": "config1"
"updated_by": "system"
}
}
}
Expand Down

0 comments on commit 54348a7

Please sign in to comment.