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

[Ingest Manager] Add ability to sort to agent configs and package configs #70676

Merged
merged 3 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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' },
Copy link
Contributor Author

@jen-huang jen-huang Jul 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • id was removed as it's not used (saved object ID is separate and does not need to be declared on mappings)
  • name changed to keyword to enable sorting on this field (consistent with name fields on our other objects)

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