Skip to content

Commit

Permalink
Return number of policies from data source, surface in assign data so…
Browse files Browse the repository at this point in the history
…urce UI
  • Loading branch information
jen-huang committed Dec 17, 2019
1 parent 566bbb0 commit 21fb651
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export const AssignDatasourcesFlyout: React.FC<Props> = ({
<EuiFlyoutBody>
<DatasourcesTable
datasources={datasources}
withPoliciesCount={true}
loading={isDatasourcesLoading}
message={getTableMessage()}
search={{
Expand All @@ -184,6 +185,19 @@ export const AssignDatasourcesFlyout: React.FC<Props> = ({
incremental: true,
schema: true,
},
filters: [
{
type: 'field_value_toggle',
field: 'policies',
value: 0,
name: (
<FormattedMessage
id="xpack.fleet.assignDatasources.unassignedFilterButtonLabel"
defaultMessage="Unassigned"
/>
),
},
],
}}
selection={{
onSelectionChange: (selection: Datasource[]) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiInMemoryTable, EuiInMemoryTableProps, EuiLink } from '@elastic/eui';
import { EuiInMemoryTable, EuiInMemoryTableProps, EuiLink, EuiBadge } from '@elastic/eui';
import { Datasource } from '../../../../common/types/domain_data';
import { useLibs } from '../../../hooks';

interface Props extends EuiInMemoryTableProps {
datasources?: Datasource[];
datasources?: Array<Datasource & { policies?: string[] }>;
withPoliciesCount?: boolean;
}

export const DatasourcesTable: React.FC<Props> = ({
datasources: originalDatasources,
...rest
}) => {
export const DatasourcesTable: React.FC<Props> = (
{ datasources: originalDatasources, withPoliciesCount, ...rest } = {
datasources: [],
withPoliciesCount: false,
}
) => {
const { framework } = useLibs();

// Flatten some values so that they can be searched via in-memory table search
Expand All @@ -32,6 +35,7 @@ export const DatasourcesTable: React.FC<Props> = ({
version: packageVersion,
description: packageDescription,
},
policies,
}) => ({
id,
name,
Expand All @@ -40,73 +44,88 @@ export const DatasourcesTable: React.FC<Props> = ({
packageTitle,
packageVersion,
packageDescription,
policies: policies?.length || 0,
})
);

const columns: EuiInMemoryTableProps['columns'] = [
{
field: 'name',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.nameColumnTitle', {
defaultMessage: 'Name',
}),
},
{
field: 'packageTitle',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.packageNameColumnTitle', {
defaultMessage: 'Package',
}),
},
{
field: 'packageVersion',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.packageVersionColumnTitle', {
defaultMessage: 'Version',
}),
},
{
field: 'streams',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.streamsCountColumnTitle', {
defaultMessage: 'Streams',
}),
},
{
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.actionsColumnTitle', {
defaultMessage: 'Actions',
}),
actions: [
{
render: ({ packageName, packageVersion }: any) => {
return (
<EuiLink
color="primary"
external
target="_blank"
href={`${window.location.origin}${framework.info.basePath}/app/epm#/detail/${packageName}-${packageVersion}`}
>
<FormattedMessage
id="xpack.fleet.policyDetails.datasourcesTable.viewActionLinkText"
defaultMessage="view"
/>
</EuiLink>
);
},
},
],
width: '100px',
},
];

if (withPoliciesCount) {
columns.splice(columns.length - 1, 0, {
field: 'policies',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.policiesColumnTitle', {
defaultMessage: 'Policies',
}),
render: (policies: number) => {
return policies === 0 ? (
<EuiBadge>
<FormattedMessage
id="xpack.fleet.policyDetails.datasourcesTable.unassignedLabelText"
defaultMessage="Unassigned"
/>
</EuiBadge>
) : (
policies
);
},
});
}

return (
<EuiInMemoryTable
itemId="id"
items={datasources}
columns={[
{
field: 'name',
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.ameColumnTitle', {
defaultMessage: 'Name',
}),
},
{
field: 'packageTitle',
name: i18n.translate(
'xpack.fleet.policyDetails.datasourcesTable.packageNameColumnTitle',
{
defaultMessage: 'Package',
}
),
},
{
field: 'packageVersion',
name: i18n.translate(
'xpack.fleet.policyDetails.datasourcesTable.packageVersionColumnTitle',
{
defaultMessage: 'Version',
}
),
},
{
field: 'streams',
name: i18n.translate(
'xpack.fleet.policyDetails.datasourcesTable.streamsCountColumnTitle',
{
defaultMessage: 'Streams',
}
),
},
{
name: i18n.translate('xpack.fleet.policyDetails.datasourcesTable.actionsColumnTitle', {
defaultMessage: 'Actions',
}),
actions: [
{
render: ({ packageName, packageVersion }: any) => {
return (
<EuiLink
color="primary"
external
target="_blank"
href={`${window.location.origin}${framework.info.basePath}/app/epm#/detail/${packageName}-${packageVersion}`}
>
<FormattedMessage
id="xpack.fleet.policyDetails.datasourcesTable.viewActionLinkText"
defaultMessage="view"
/>
</EuiLink>
);
},
},
],
width: '100px',
},
]}
columns={columns}
sorting={{
field: 'name',
direction: 'asc',
Expand Down
27 changes: 21 additions & 6 deletions x-pack/legacy/plugins/ingest/server/libs/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,40 @@ export class PolicyLib {
kuery?: string;
page?: number;
perPage?: number;
withDatasources?: boolean;
} = {
page: 1,
perPage: 20,
withDatasources: true,
}
): Promise<{ items: Policy[]; total: number; page: number; perPage: number }> {
const response = await this.adapter.list(user, options);

const dataSourcesIds = unique(flatten(response.items.map(policy => policy.datasources || [])));

const datasources: Datasource[] = await this.libs.datasources.getByIDs(user, dataSourcesIds);
if (options.withDatasources) {
const dataSourcesIds = unique(
flatten(response.items.map(policy => policy.datasources || []))
);
const datasources: Datasource[] = await this.libs.datasources.getByIDs(user, dataSourcesIds);

return {
...response,
items: response.items.map(policy => {
return {
...policy,
datasources: (policy.datasources || []).map(id => {
return datasources.find(ds => ds.id === id);
}),
} as Policy;
}),
};
}

return {
...response,
items: response.items.map(policy => {
return {
...policy,
datasources: (policy.datasources || []).map(id => {
return datasources.find(ds => ds.id === id);
}),
datasources: undefined,
} as Policy;
}),
};
Expand Down
50 changes: 45 additions & 5 deletions x-pack/legacy/plugins/ingest/server/rest_api/datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,25 @@ export const createGETDatasourceRoute = (libs: ServerLibs) => ({
config: {},
handler: (async (
request: FrameworkRequest<{ params: { datasourceId: string } }>
): Promise<ReturnTypeGet<any>> => {
): Promise<ReturnTypeGet<(Datasource & { policies: string[] }) | null>> => {
const datasource = await libs.datasources.get(request.user, request.params.datasourceId);

return { item: datasource, success: true };
if (datasource) {
const policies = await libs.policy.list(request.user, {
kuery: `policies.datasources:"${datasource.id}"`,
page: 1,
perPage: 10000,
withDatasources: false,
});
return {
item: {
...datasource,
policies: policies.items.map(p => p.id),
},
success: true,
};
} else {
return { item: null, success: false };
}
}) as FrameworkRouteHandler,
});

Expand All @@ -56,21 +71,46 @@ export const createGETDatasourcesRoute = (libs: ServerLibs) => ({
},
},
},
handler: async (request: FrameworkRequest<any>): Promise<ReturnTypeList<Datasource>> => {
handler: async (
request: FrameworkRequest<any>
): Promise<ReturnTypeList<Datasource & { policies: string[] }>> => {
// TODO fix for types that broke in TS 3.7
const query: {
page: string;
perPage: string;
kuery: string;
showInactive: string;
} = request.query as any;

const { items, total, page, perPage } = await libs.datasources.list(request.user, {
page: parseInt(query.page, 10),
perPage: parseInt(query.perPage, 10),
kuery: query.kuery,
});

return { list: items, success: true, total, page, perPage };
const list: Array<Datasource & { policies: string[] }> = [];

// TODO: this could be optimized so that it is not sequentially blocking
for (const ds of items) {
const policies = await libs.policy.list(request.user, {
kuery: `policies.datasources:"${ds.id}"`,
page: 1,
perPage: 10000,
withDatasources: false,
});
list.push({
...ds,
policies: policies.items.map(p => p.id),
});
}

return {
list,
success: true,
total,
page,
perPage,
};
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const createGETPoliciesRoute = (libs: ServerLibs) => ({
page: parseInt(query.page, 10),
perPage: parseInt(query.perPage, 10),
kuery: query.kuery,
withDatasources: true,
});

return { list: items, success: true, total, page, perPage };
Expand Down

0 comments on commit 21fb651

Please sign in to comment.