mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Enterprise Search] Adds a job detail flyout for connectors (#144794)
## Summary This adds a jobs flyout to the overview page of every connector index. <img width="748" alt="Screenshot 2022-11-08 at 11 56 58" src="https://user-images.githubusercontent.com/94373878/200548683-3255fab2-12e5-4dba-9fb6-38d009c93d69.png">
This commit is contained in:
parent
098b5db77b
commit
a7fdac4564
29 changed files with 1747 additions and 56 deletions
|
@ -98,6 +98,11 @@ export interface FilteringConfig {
|
|||
draft: FilteringRules;
|
||||
}
|
||||
|
||||
export enum TriggerMethod {
|
||||
ON_DEMAND = 'on-demand',
|
||||
SCHEDULED = 'scheduled',
|
||||
}
|
||||
|
||||
export interface Connector {
|
||||
api_key_id: string | null;
|
||||
configuration: ConnectorConfiguration;
|
||||
|
@ -126,14 +131,25 @@ export interface Connector {
|
|||
export type ConnectorDocument = Omit<Connector, 'id'>;
|
||||
|
||||
export interface ConnectorSyncJob {
|
||||
cancelation_requested_at: string | null;
|
||||
canceled_at: string | null;
|
||||
completed_at: string | null;
|
||||
connector?: ConnectorDocument;
|
||||
connector_id: string;
|
||||
created_at: string;
|
||||
deleted_document_count: number;
|
||||
error: string | null;
|
||||
filtering: FilteringRules | null;
|
||||
id: string;
|
||||
index_name: string;
|
||||
indexed_document_count: number;
|
||||
indexed_document_volume: number;
|
||||
last_seen: string;
|
||||
metadata: Record<string, unknown>;
|
||||
pipeline: IngestPipelineParams | null;
|
||||
started_at: string;
|
||||
status: SyncStatus;
|
||||
trigger_method: TriggerMethod;
|
||||
worker_hostname: string;
|
||||
}
|
||||
|
||||
export type ConnectorSyncJobDocument = Omit<ConnectorSyncJob, 'id'>;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
import { ConnectorSyncJob, TriggerMethod, SyncStatus } from '../../../../common/types/connectors';
|
||||
import { SyncJobView } from '../components/search_index/sync_jobs/sync_jobs_view_logic';
|
||||
|
||||
export const syncJob: ConnectorSyncJob = {
|
||||
cancelation_requested_at: null,
|
||||
canceled_at: null,
|
||||
completed_at: '2022-09-05T15:59:39.816+00:00',
|
||||
connector_id: 'we2284IBjobuR2-lAuXh',
|
||||
created_at: '2022-09-05T14:59:39.816+00:00',
|
||||
deleted_document_count: 20,
|
||||
error: null,
|
||||
filtering: null,
|
||||
id: 'id',
|
||||
index_name: 'indexName',
|
||||
indexed_document_count: 50,
|
||||
indexed_document_volume: 40,
|
||||
last_seen: '2022-09-05T15:59:39.816+00:00',
|
||||
metadata: {},
|
||||
pipeline: null,
|
||||
trigger_method: TriggerMethod.ON_DEMAND,
|
||||
started_at: '2022-09-05T14:59:39.816+00:00',
|
||||
status: SyncStatus.COMPLETED,
|
||||
worker_hostname: 'hostname_fake',
|
||||
};
|
||||
|
||||
export const syncJobView: SyncJobView = {
|
||||
...syncJob,
|
||||
duration: moment.duration(1, 'hour'),
|
||||
lastSync: '2022-09-05T15:59:39.816+00:00',
|
||||
};
|
|
@ -22,7 +22,7 @@ import { CrawlRequestsPanel } from './crawler/crawl_requests_panel/crawl_request
|
|||
import { CrawlerTotalStats } from './crawler_total_stats';
|
||||
import { GenerateApiKeyPanel } from './generate_api_key_panel';
|
||||
import { OverviewLogic } from './overview.logic';
|
||||
import { SyncJobs } from './sync_jobs';
|
||||
import { SyncJobs } from './sync_jobs/sync_jobs';
|
||||
|
||||
export const SearchIndexOverview: React.FC = () => {
|
||||
const { indexData } = useValues(OverviewLogic);
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DocumentsPanel renders 1`] = `
|
||||
<FlyoutPanel
|
||||
title="Documents"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "added",
|
||||
"name": "Added",
|
||||
},
|
||||
Object {
|
||||
"field": "removed",
|
||||
"name": "Removed",
|
||||
},
|
||||
Object {
|
||||
"field": "total",
|
||||
"name": "Total",
|
||||
},
|
||||
Object {
|
||||
"field": "volume",
|
||||
"name": "Volume",
|
||||
"render": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"added": 10,
|
||||
"removed": 0,
|
||||
"total": 305,
|
||||
"volume": 1120,
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
`;
|
|
@ -0,0 +1,115 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EventsPanel renders 1`] = `
|
||||
<FlyoutPanel
|
||||
title="Events"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "title",
|
||||
"name": "State",
|
||||
"width": "50%",
|
||||
},
|
||||
Object {
|
||||
"field": "date",
|
||||
"name": "Time",
|
||||
"width": "50%",
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Canceled",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Cancelation requested",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Completed",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Last updated",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Sync started",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Sync requested manually",
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
`;
|
||||
|
||||
exports[`EventsPanel renders with some values missing 1`] = `
|
||||
<FlyoutPanel
|
||||
title="Events"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "title",
|
||||
"name": "State",
|
||||
"width": "50%",
|
||||
},
|
||||
Object {
|
||||
"field": "date",
|
||||
"name": "Time",
|
||||
"width": "50%",
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Canceled",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Completed",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Last updated",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Sync started",
|
||||
},
|
||||
Object {
|
||||
"date": "Mon Oct 24 2022 02:44:19 GMT+0000",
|
||||
"title": "Sync requested manually",
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
`;
|
|
@ -0,0 +1,202 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FilteringPanel renders 1`] = `
|
||||
<Fragment>
|
||||
<FlyoutPanel
|
||||
title="Filtering"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "policy",
|
||||
"name": "Pipeline setting",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "rule",
|
||||
"name": "Rule",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "value",
|
||||
"name": "Value",
|
||||
"render": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
items={Array []}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`FilteringPanel renders advanced snippet 1`] = `
|
||||
<Fragment>
|
||||
<FlyoutPanel
|
||||
title="Filtering"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "policy",
|
||||
"name": "Pipeline setting",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "rule",
|
||||
"name": "Rule",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "value",
|
||||
"name": "Value",
|
||||
"render": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"order": 0,
|
||||
"policy": "include",
|
||||
"rule": "equals",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 1,
|
||||
"policy": "exclude",
|
||||
"rule": "contains",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 2,
|
||||
"policy": "exclude",
|
||||
"rule": "ends_with",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 4,
|
||||
"policy": "exclude",
|
||||
"rule": "<",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 5,
|
||||
"policy": "include",
|
||||
"rule": ">",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
<EuiSpacer />
|
||||
<FlyoutPanel
|
||||
title="Advanced filtering rules"
|
||||
>
|
||||
<EuiPanel
|
||||
hasShadow={false}
|
||||
>
|
||||
<EuiCodeBlock
|
||||
language="json"
|
||||
transparentBackground={true}
|
||||
>
|
||||
{
|
||||
"one": "two",
|
||||
"three": "four"
|
||||
}
|
||||
</EuiCodeBlock>
|
||||
</EuiPanel>
|
||||
</FlyoutPanel>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`FilteringPanel renders filtering rules list 1`] = `
|
||||
<Fragment>
|
||||
<FlyoutPanel
|
||||
title="Filtering"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "policy",
|
||||
"name": "Pipeline setting",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "rule",
|
||||
"name": "Rule",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "value",
|
||||
"name": "Value",
|
||||
"render": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"order": 0,
|
||||
"policy": "include",
|
||||
"rule": "equals",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 1,
|
||||
"policy": "exclude",
|
||||
"rule": "contains",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 2,
|
||||
"policy": "exclude",
|
||||
"rule": "ends_with",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 4,
|
||||
"policy": "exclude",
|
||||
"rule": "<",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
Object {
|
||||
"order": 5,
|
||||
"policy": "include",
|
||||
"rule": ">",
|
||||
"value": "THIS VALUE",
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
</Fragment>
|
||||
`;
|
|
@ -0,0 +1,18 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FlyoutPanel renders 1`] = `
|
||||
<EuiPanel
|
||||
color="subdued"
|
||||
hasShadow={false}
|
||||
paddingSize="l"
|
||||
>
|
||||
<EuiTitle
|
||||
size="xs"
|
||||
>
|
||||
<h4>
|
||||
Title
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer />
|
||||
</EuiPanel>
|
||||
`;
|
|
@ -0,0 +1,50 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PipelinePanel renders 1`] = `
|
||||
<FlyoutPanel
|
||||
title="Pipeline"
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "setting",
|
||||
"name": "Pipeline setting",
|
||||
},
|
||||
Object {
|
||||
"field": "value",
|
||||
"name": "Value",
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"setting": "Pipeline name",
|
||||
"value": "name",
|
||||
},
|
||||
Object {
|
||||
"setting": "Extract binary content",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"setting": "Reduce whitespace",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"setting": "Machine learning inference",
|
||||
"value": false,
|
||||
},
|
||||
]
|
||||
}
|
||||
noItemsMessage={
|
||||
<EuiI18n
|
||||
default="No items found"
|
||||
token="euiBasicTable.noItemsMessage"
|
||||
/>
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
`;
|
|
@ -0,0 +1,152 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SyncCalloutsPanel renders 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title="Sync complete"
|
||||
>
|
||||
Completed at Mon Sep 05 2022 15:59:39 GMT+0000
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title="Sync started manually"
|
||||
>
|
||||
Started at Mon Sep 05 2022 14:59:39 GMT+0000.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`SyncCalloutsPanel renders canceled job 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title="Sync complete"
|
||||
>
|
||||
Completed at Mon Sep 05 2022 15:59:39 GMT+0000
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
title="Sync canceled"
|
||||
>
|
||||
Sync canceled at .
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title="Sync started manually"
|
||||
>
|
||||
Started at Mon Sep 05 2022 14:59:39 GMT+0000.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`SyncCalloutsPanel renders different trigger method 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title="Sync complete"
|
||||
>
|
||||
Completed at Mon Sep 05 2022 15:59:39 GMT+0000
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="clock"
|
||||
title="In progress"
|
||||
>
|
||||
Sync has been running for 1h 0m 0s.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title="Sync started by schedule"
|
||||
>
|
||||
Started at Mon Sep 05 2022 14:59:39 GMT+0000.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`SyncCalloutsPanel renders error job 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title="Sync complete"
|
||||
>
|
||||
Completed at Mon Sep 05 2022 15:59:39 GMT+0000
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
title="Sync failure"
|
||||
>
|
||||
Sync failure: .
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title="Sync started manually"
|
||||
>
|
||||
Started at Mon Sep 05 2022 14:59:39 GMT+0000.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`SyncCalloutsPanel renders in progress job 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title="Sync complete"
|
||||
>
|
||||
Completed at Mon Sep 05 2022 15:59:39 GMT+0000
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="clock"
|
||||
title="In progress"
|
||||
>
|
||||
Sync has been running for 1h 0m 0s.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title="Sync started manually"
|
||||
>
|
||||
Started at Mon Sep 05 2022 14:59:39 GMT+0000.
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
`;
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { SyncJobDocumentsPanel } from './documents_panel';
|
||||
|
||||
describe('DocumentsPanel', () => {
|
||||
const documents = {
|
||||
added: 10,
|
||||
removed: 0,
|
||||
total: 305,
|
||||
volume: 1120,
|
||||
};
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<SyncJobDocumentsPanel {...documents} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
import { ByteSizeValue } from '@kbn/config-schema';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
|
||||
interface SyncJobDocumentsPanelProps {
|
||||
added: number;
|
||||
removed: number;
|
||||
total: number;
|
||||
volume: number;
|
||||
}
|
||||
|
||||
export const SyncJobDocumentsPanel: React.FC<SyncJobDocumentsPanelProps> = (syncJobDocuments) => {
|
||||
const columns: Array<EuiBasicTableColumn<SyncJobDocumentsPanelProps>> = [
|
||||
{
|
||||
field: 'added',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.added', {
|
||||
defaultMessage: 'Added',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'removed',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.removed', {
|
||||
defaultMessage: 'Removed',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'total',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.total', {
|
||||
defaultMessage: 'Total',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'volume',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.volume', {
|
||||
defaultMessage: 'Volume',
|
||||
}),
|
||||
render: (volume: number) => new ByteSizeValue(volume).toString(),
|
||||
},
|
||||
];
|
||||
return (
|
||||
<FlyoutPanel
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.title', {
|
||||
defaultMessage: 'Documents',
|
||||
})}
|
||||
>
|
||||
<EuiBasicTable columns={columns} items={[syncJobDocuments]} />
|
||||
</FlyoutPanel>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { TriggerMethod } from '../../../../../../common/types/connectors';
|
||||
|
||||
import { SyncJobEventsPanel } from './events_panel';
|
||||
|
||||
describe('EventsPanel', () => {
|
||||
const events = {
|
||||
cancelationRequestedAt: '2022-10-24T02:44:19.660365+00:00',
|
||||
canceledAt: '2022-10-24T02:44:19.660365+00:00',
|
||||
completed: '2022-10-24T02:44:19.660365+00:00',
|
||||
lastUpdated: '2022-10-24T02:44:19.660365+00:00',
|
||||
syncRequestedAt: '2022-10-24T02:44:19.660365+00:00',
|
||||
syncStarted: '2022-10-24T02:44:19.660365+00:00',
|
||||
triggerMethod: TriggerMethod.ON_DEMAND,
|
||||
};
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<SyncJobEventsPanel {...events} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders with some values missing', () => {
|
||||
const wrapper = shallow(
|
||||
<SyncJobEventsPanel
|
||||
{...events}
|
||||
cancelationRequestedAt=""
|
||||
triggerMethod={TriggerMethod.ON_DEMAND}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { TriggerMethod } from '../../../../../../common/types/connectors';
|
||||
import { dateToString } from '../../../utils/date_to_string';
|
||||
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
|
||||
export interface SyncJobsEventPanelProps {
|
||||
cancelationRequestedAt?: string;
|
||||
canceledAt?: string;
|
||||
completed?: string;
|
||||
lastUpdated?: string;
|
||||
syncRequestedAt?: string;
|
||||
syncStarted?: string;
|
||||
triggerMethod: TriggerMethod;
|
||||
}
|
||||
|
||||
interface SyncJobEvent {
|
||||
date?: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const SyncJobEventsPanel: React.FC<SyncJobsEventPanelProps> = ({
|
||||
cancelationRequestedAt,
|
||||
canceledAt,
|
||||
completed,
|
||||
lastUpdated,
|
||||
syncRequestedAt,
|
||||
syncStarted,
|
||||
triggerMethod,
|
||||
}) => {
|
||||
const events: SyncJobEvent[] = [
|
||||
{
|
||||
date: dateToString(syncRequestedAt),
|
||||
title:
|
||||
triggerMethod === TriggerMethod.ON_DEMAND
|
||||
? i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.events.syncRequestedManually',
|
||||
{ defaultMessage: 'Sync requested manually' }
|
||||
)
|
||||
: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.events.syncRequestedScheduled',
|
||||
{ defaultMessage: 'Sync requested by schedule' }
|
||||
),
|
||||
},
|
||||
{
|
||||
date: dateToString(syncStarted),
|
||||
title: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.syncStarted', {
|
||||
defaultMessage: 'Sync started',
|
||||
}),
|
||||
},
|
||||
{
|
||||
date: dateToString(lastUpdated),
|
||||
title: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.lastUpdated', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
},
|
||||
{
|
||||
date: dateToString(completed),
|
||||
title: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.completed', {
|
||||
defaultMessage: 'Completed',
|
||||
}),
|
||||
},
|
||||
{
|
||||
date: dateToString(cancelationRequestedAt),
|
||||
title: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.events.cancelationRequested',
|
||||
{
|
||||
defaultMessage: 'Cancelation requested',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
date: dateToString(canceledAt),
|
||||
title: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.canceled', {
|
||||
defaultMessage: 'Canceled',
|
||||
}),
|
||||
},
|
||||
]
|
||||
.filter(({ date }) => !!date)
|
||||
.sort(({ date }, { date: dateB }) => (moment(date).isAfter(moment(dateB)) ? 1 : -1));
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<SyncJobEvent>> = [
|
||||
{
|
||||
field: 'title',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.state', {
|
||||
defaultMessage: 'State',
|
||||
}),
|
||||
width: '50%',
|
||||
},
|
||||
{
|
||||
field: 'date',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.time', {
|
||||
defaultMessage: 'Time',
|
||||
}),
|
||||
width: '50%',
|
||||
},
|
||||
];
|
||||
return (
|
||||
<FlyoutPanel
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.events.title', {
|
||||
defaultMessage: 'Events',
|
||||
})}
|
||||
>
|
||||
<EuiBasicTable columns={columns} items={events} />
|
||||
</FlyoutPanel>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import {
|
||||
FilteringPolicy,
|
||||
FilteringRule,
|
||||
FilteringRuleRule,
|
||||
} from '../../../../../../common/types/connectors';
|
||||
|
||||
import { FilteringPanel } from './filtering_panel';
|
||||
|
||||
describe('FilteringPanel', () => {
|
||||
const filteringRules = [
|
||||
{
|
||||
order: 1,
|
||||
policy: FilteringPolicy.EXCLUDE,
|
||||
rule: FilteringRuleRule.CONTAINS,
|
||||
value: 'THIS VALUE',
|
||||
},
|
||||
{
|
||||
order: 2,
|
||||
policy: FilteringPolicy.EXCLUDE,
|
||||
rule: FilteringRuleRule.ENDS_WITH,
|
||||
value: 'THIS VALUE',
|
||||
},
|
||||
{
|
||||
order: 0,
|
||||
policy: FilteringPolicy.INCLUDE,
|
||||
rule: FilteringRuleRule.EQUALS,
|
||||
value: 'THIS VALUE',
|
||||
},
|
||||
{
|
||||
order: 5,
|
||||
policy: FilteringPolicy.INCLUDE,
|
||||
rule: FilteringRuleRule.GT,
|
||||
value: 'THIS VALUE',
|
||||
},
|
||||
{
|
||||
order: 4,
|
||||
policy: FilteringPolicy.EXCLUDE,
|
||||
rule: FilteringRuleRule.LT,
|
||||
value: 'THIS VALUE',
|
||||
},
|
||||
] as FilteringRule[];
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<FilteringPanel filteringRules={[]} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders filtering rules list', () => {
|
||||
const wrapper = shallow(<FilteringPanel filteringRules={filteringRules} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders advanced snippet', () => {
|
||||
const wrapper = shallow(
|
||||
<FilteringPanel
|
||||
advancedSnippet={{
|
||||
created_at: 'whatever',
|
||||
updated_at: 'sometime',
|
||||
value: { one: 'two', three: 'four' },
|
||||
}}
|
||||
filteringRules={filteringRules}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
EuiBasicTable,
|
||||
EuiBasicTableColumn,
|
||||
EuiCode,
|
||||
EuiCodeBlock,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import {
|
||||
FilteringPolicy,
|
||||
FilteringRule,
|
||||
FilteringRuleRule,
|
||||
FilteringRules,
|
||||
} from '../../../../../../common/types/connectors';
|
||||
|
||||
import { filteringRuleToText, filteringPolicyToText } from '../../../utils/filtering_rule_helpers';
|
||||
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
|
||||
interface FilteringPanelProps {
|
||||
advancedSnippet?: FilteringRules['advanced_snippet'];
|
||||
filteringRules: FilteringRule[];
|
||||
}
|
||||
|
||||
export const FilteringPanel: React.FC<FilteringPanelProps> = ({
|
||||
advancedSnippet,
|
||||
filteringRules,
|
||||
}) => {
|
||||
const columns: Array<EuiBasicTableColumn<FilteringRule>> = [
|
||||
{
|
||||
field: 'policy',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.filtering.policy', {
|
||||
defaultMessage: 'Pipeline setting',
|
||||
}),
|
||||
render: (policy: FilteringPolicy) => filteringPolicyToText(policy),
|
||||
},
|
||||
{
|
||||
field: 'rule',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.filtering.rule', {
|
||||
defaultMessage: 'Rule',
|
||||
}),
|
||||
render: (rule: FilteringRuleRule) => filteringRuleToText(rule),
|
||||
},
|
||||
{
|
||||
field: 'value',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.filtering.value', {
|
||||
defaultMessage: 'Value',
|
||||
}),
|
||||
render: (value: string) => <EuiCode>{value}</EuiCode>,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<FlyoutPanel
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.filteringTitle', {
|
||||
defaultMessage: 'Filtering',
|
||||
})}
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={columns}
|
||||
items={filteringRules.sort(({ order }, { order: secondOrder }) => order - secondOrder)}
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
{!!advancedSnippet?.value ? (
|
||||
<>
|
||||
<EuiSpacer />
|
||||
<FlyoutPanel
|
||||
title={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.filteringAdvancedTitle',
|
||||
{
|
||||
defaultMessage: 'Advanced filtering rules',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<EuiPanel hasShadow={false}>
|
||||
<EuiCodeBlock transparentBackground language="json">
|
||||
{JSON.stringify(advancedSnippet.value, undefined, 2)}
|
||||
</EuiCodeBlock>
|
||||
</EuiPanel>
|
||||
</FlyoutPanel>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
|
||||
describe('FlyoutPanel', () => {
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<FlyoutPanel title="Title" />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
|
||||
interface FlyoutPanelProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const FlyoutPanel: React.FC<FlyoutPanelProps> = ({ children, title }) => {
|
||||
return (
|
||||
<EuiPanel paddingSize="l" color="subdued" hasShadow={false}>
|
||||
<EuiTitle size="xs">
|
||||
<h4>{title}</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer />
|
||||
{children}
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { PipelinePanel } from './pipeline_panel';
|
||||
|
||||
describe('PipelinePanel', () => {
|
||||
const pipeline = {
|
||||
extract_binary_content: true,
|
||||
name: 'name',
|
||||
reduce_whitespace: true,
|
||||
run_ml_inference: false,
|
||||
};
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<PipelinePanel pipeline={pipeline} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { IngestPipelineParams } from '../../../../../../common/types/connectors';
|
||||
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
|
||||
interface PipelinePanelProps {
|
||||
pipeline: IngestPipelineParams;
|
||||
}
|
||||
|
||||
export const PipelinePanel: React.FC<PipelinePanelProps> = ({ pipeline }) => {
|
||||
const items: Array<{ setting: string; value: string | boolean }> = [
|
||||
{
|
||||
setting: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.pipeline.name', {
|
||||
defaultMessage: 'Pipeline name',
|
||||
}),
|
||||
value: pipeline.name,
|
||||
},
|
||||
{
|
||||
setting: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.pipeline.extractBinaryContent',
|
||||
{
|
||||
defaultMessage: 'Extract binary content',
|
||||
}
|
||||
),
|
||||
value: pipeline.extract_binary_content,
|
||||
},
|
||||
{
|
||||
setting: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.pipeline.reduceWhitespace',
|
||||
{
|
||||
defaultMessage: 'Reduce whitespace',
|
||||
}
|
||||
),
|
||||
value: pipeline.reduce_whitespace,
|
||||
},
|
||||
{
|
||||
setting: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.pipeline.runMlInference',
|
||||
{
|
||||
defaultMessage: 'Machine learning inference',
|
||||
}
|
||||
),
|
||||
value: pipeline.run_ml_inference,
|
||||
},
|
||||
];
|
||||
const columns: Array<EuiBasicTableColumn<{ setting: string; value: string | boolean }>> = [
|
||||
{
|
||||
field: 'setting',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.pipeline.setting', {
|
||||
defaultMessage: 'Pipeline setting',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'value',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.documents.value', {
|
||||
defaultMessage: 'Value',
|
||||
}),
|
||||
},
|
||||
];
|
||||
return (
|
||||
<FlyoutPanel
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.index.syncJobs.pipeline.title', {
|
||||
defaultMessage: 'Pipeline',
|
||||
})}
|
||||
>
|
||||
<EuiBasicTable columns={columns} items={items} />
|
||||
</FlyoutPanel>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { syncJobView } from '../../../__mocks__/sync_job.mock';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { SyncStatus, TriggerMethod } from '../../../../../../common/types/connectors';
|
||||
|
||||
import { SyncJobCallouts } from './sync_callouts';
|
||||
|
||||
describe('SyncCalloutsPanel', () => {
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<SyncJobCallouts syncJob={syncJobView} />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders error job', () => {
|
||||
const wrapper = shallow(
|
||||
<SyncJobCallouts syncJob={{ ...syncJobView, status: SyncStatus.ERROR }} />
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders canceled job', () => {
|
||||
const wrapper = shallow(
|
||||
<SyncJobCallouts syncJob={{ ...syncJobView, status: SyncStatus.CANCELED }} />
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders in progress job', () => {
|
||||
const wrapper = shallow(
|
||||
<SyncJobCallouts syncJob={{ ...syncJobView, status: SyncStatus.IN_PROGRESS }} />
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders different trigger method', () => {
|
||||
const wrapper = shallow(
|
||||
<SyncJobCallouts
|
||||
syncJob={{
|
||||
...syncJobView,
|
||||
status: SyncStatus.IN_PROGRESS,
|
||||
trigger_method: TriggerMethod.SCHEDULED,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiFlexItem, EuiCallOut } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { SyncStatus, TriggerMethod } from '../../../../../../common/types/connectors';
|
||||
|
||||
import { dateToString } from '../../../utils/date_to_string';
|
||||
import { durationToText } from '../../../utils/duration_to_text';
|
||||
|
||||
import { SyncJobView } from './sync_jobs_view_logic';
|
||||
|
||||
interface SyncJobCalloutsProps {
|
||||
syncJob: SyncJobView;
|
||||
}
|
||||
|
||||
export const SyncJobCallouts: React.FC<SyncJobCalloutsProps> = ({ syncJob }) => {
|
||||
return (
|
||||
<>
|
||||
{!!syncJob.completed_at && (
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="success"
|
||||
iconType="check"
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.completedTitle', {
|
||||
defaultMessage: 'Sync complete',
|
||||
})}
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.completedDescription', {
|
||||
defaultMessage: 'Completed at {date}',
|
||||
values: {
|
||||
date: dateToString(syncJob.completed_at),
|
||||
},
|
||||
})}
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{syncJob.status === SyncStatus.ERROR && (
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.failureTitle', {
|
||||
defaultMessage: 'Sync failure',
|
||||
})}
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.failureDescription', {
|
||||
defaultMessage: 'Sync failure: {error}.',
|
||||
values: {
|
||||
error: syncJob.error,
|
||||
},
|
||||
})}
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{syncJob.status === SyncStatus.CANCELED && (
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.canceledTitle', {
|
||||
defaultMessage: 'Sync canceled',
|
||||
})}
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.canceledDescription', {
|
||||
defaultMessage: 'Sync canceled at {date}.',
|
||||
values: {
|
||||
date: dateToString(syncJob.canceled_at ?? ''),
|
||||
},
|
||||
})}
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{syncJob.status === SyncStatus.IN_PROGRESS && (
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="clock"
|
||||
title={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.syncJobs.flyout.inProgressTitle',
|
||||
{
|
||||
defaultMessage: 'In progress',
|
||||
}
|
||||
)}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.syncJobs.flyout.inProgressDescription',
|
||||
{
|
||||
defaultMessage: 'Sync has been running for {duration}.',
|
||||
values: {
|
||||
duration: durationToText(syncJob.duration),
|
||||
},
|
||||
}
|
||||
)}
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{!!syncJob.started_at && (
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="iInCircle"
|
||||
title={
|
||||
syncJob.trigger_method === TriggerMethod.ON_DEMAND
|
||||
? i18n.translate(
|
||||
'xpack.enterpriseSearch.content.syncJobs.flyout.syncStartedManually',
|
||||
{
|
||||
defaultMessage: 'Sync started manually',
|
||||
}
|
||||
)
|
||||
: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.syncJobs.flyout.syncStartedScheduled',
|
||||
{
|
||||
defaultMessage: 'Sync started by schedule',
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.startedAtDescription', {
|
||||
defaultMessage: 'Started at {date}.',
|
||||
values: {
|
||||
date: dateToString(syncJob.started_at),
|
||||
},
|
||||
})}
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
EuiBasicTable,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFlyout,
|
||||
EuiFlyoutBody,
|
||||
EuiFlyoutHeader,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { SyncJobDocumentsPanel } from './documents_panel';
|
||||
import { SyncJobEventsPanel } from './events_panel';
|
||||
import { FilteringPanel } from './filtering_panel';
|
||||
import { FlyoutPanel } from './flyout_panel';
|
||||
import { PipelinePanel } from './pipeline_panel';
|
||||
import { SyncJobCallouts } from './sync_callouts';
|
||||
import { SyncJobView } from './sync_jobs_view_logic';
|
||||
|
||||
interface SyncJobFlyoutProps {
|
||||
onClose: () => void;
|
||||
syncJob?: SyncJobView;
|
||||
}
|
||||
|
||||
export const SyncJobFlyout: React.FC<SyncJobFlyoutProps> = ({ onClose, syncJob }) => {
|
||||
const visible = !!syncJob;
|
||||
return visible ? (
|
||||
<EuiFlyout onClose={onClose}>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.title', {
|
||||
defaultMessage: 'Event log',
|
||||
})}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<EuiFlexGroup direction="column">
|
||||
<SyncJobCallouts syncJob={syncJob} />
|
||||
<EuiFlexItem>
|
||||
<FlyoutPanel
|
||||
title={i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.sync', {
|
||||
defaultMessage: 'Sync',
|
||||
})}
|
||||
>
|
||||
<EuiBasicTable
|
||||
columns={[
|
||||
{
|
||||
field: 'id',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.syncJobs.flyout.sync.id', {
|
||||
defaultMessage: 'ID',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
items={[{ id: syncJob.id }]}
|
||||
/>
|
||||
</FlyoutPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<SyncJobDocumentsPanel
|
||||
added={syncJob.indexed_document_count}
|
||||
total={0}
|
||||
removed={syncJob.deleted_document_count}
|
||||
volume={syncJob.indexed_document_volume ?? 0}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<SyncJobEventsPanel
|
||||
canceledAt={syncJob.canceled_at ?? ''}
|
||||
cancelationRequestedAt={syncJob.cancelation_requested_at ?? ''}
|
||||
syncRequestedAt={syncJob.created_at}
|
||||
syncStarted={syncJob.started_at}
|
||||
completed={syncJob.completed_at ?? ''}
|
||||
lastUpdated={syncJob.last_seen}
|
||||
triggerMethod={syncJob.trigger_method}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<FilteringPanel
|
||||
advancedSnippet={syncJob.filtering?.advanced_snippet}
|
||||
filteringRules={syncJob.filtering?.rules ?? []}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{syncJob.pipeline && (
|
||||
<EuiFlexItem>
|
||||
<PipelinePanel pipeline={syncJob.pipeline} />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlyoutBody>
|
||||
</EuiFlyout>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
|
@ -13,20 +13,23 @@ import { EuiBadge, EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { SyncStatus } from '../../../../../common/types/connectors';
|
||||
import { SyncStatus } from '../../../../../../common/types/connectors';
|
||||
|
||||
import { FormattedDateTime } from '../../../shared/formatted_date_time';
|
||||
import { durationToText } from '../../utils/duration_to_text';
|
||||
import { FormattedDateTime } from '../../../../shared/formatted_date_time';
|
||||
import { durationToText } from '../../../utils/duration_to_text';
|
||||
|
||||
import { syncStatusToColor, syncStatusToText } from '../../utils/sync_status_to_text';
|
||||
import { syncStatusToColor, syncStatusToText } from '../../../utils/sync_status_to_text';
|
||||
|
||||
import { IndexViewLogic } from './index_view_logic';
|
||||
import { IndexViewLogic } from '../index_view_logic';
|
||||
|
||||
import { SyncJobFlyout } from './sync_job_flyout';
|
||||
import { SyncJobsViewLogic, SyncJobView } from './sync_jobs_view_logic';
|
||||
|
||||
export const SyncJobs: React.FC = () => {
|
||||
const { connectorId } = useValues(IndexViewLogic);
|
||||
const { syncJobs, syncJobsLoading, syncJobsPagination } = useValues(SyncJobsViewLogic);
|
||||
const { fetchSyncJobs } = useActions(SyncJobsViewLogic);
|
||||
const [syncJobFlyout, setSyncJobFlyout] = useState<SyncJobView | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (connectorId) {
|
||||
|
@ -47,7 +50,6 @@ export const SyncJobs: React.FC = () => {
|
|||
render: (lastSync: string) => <FormattedDateTime date={new Date(lastSync)} />,
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
field: 'duration',
|
||||
|
@ -57,7 +59,6 @@ export const SyncJobs: React.FC = () => {
|
|||
render: (duration: moment.Duration) => durationToText(duration),
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
field: 'docsCount',
|
||||
|
@ -66,7 +67,6 @@ export const SyncJobs: React.FC = () => {
|
|||
}),
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
|
@ -77,25 +77,50 @@ export const SyncJobs: React.FC = () => {
|
|||
<EuiBadge color={syncStatusToColor(syncStatus)}>{syncStatusToText(syncStatus)}</EuiBadge>
|
||||
),
|
||||
truncateText: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.actions.viewJob.title',
|
||||
{
|
||||
defaultMessage: 'View this sync job',
|
||||
}
|
||||
),
|
||||
icon: 'eye',
|
||||
isPrimary: false,
|
||||
name: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.index.syncJobs.actions.viewJob.caption',
|
||||
{
|
||||
defaultMessage: 'View this sync job',
|
||||
}
|
||||
),
|
||||
onClick: (job) => setSyncJobFlyout(job),
|
||||
type: 'icon',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiBasicTable
|
||||
items={syncJobs}
|
||||
columns={columns}
|
||||
onChange={({ page: { index, size } }: { page: { index: number; size: number } }) => {
|
||||
if (connectorId) {
|
||||
fetchSyncJobs({ connectorId, page: index, size });
|
||||
}
|
||||
}}
|
||||
pagination={{
|
||||
...syncJobsPagination,
|
||||
totalItemCount: syncJobsPagination.total,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
loading={syncJobsLoading}
|
||||
/>
|
||||
<>
|
||||
<SyncJobFlyout onClose={() => setSyncJobFlyout(undefined)} syncJob={syncJobFlyout} />
|
||||
<EuiBasicTable
|
||||
items={syncJobs}
|
||||
columns={columns}
|
||||
hasActions
|
||||
onChange={({ page: { index, size } }: { page: { index: number; size: number } }) => {
|
||||
if (connectorId) {
|
||||
fetchSyncJobs({ connectorId, page: index, size });
|
||||
}
|
||||
}}
|
||||
pagination={{
|
||||
...syncJobsPagination,
|
||||
totalItemCount: syncJobsPagination.total,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
loading={syncJobsLoading}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -5,18 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic';
|
||||
import { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic';
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
import { nextTick } from '@kbn/test-jest-helpers';
|
||||
|
||||
import { HttpError, Status } from '../../../../../common/types/api';
|
||||
import { HttpError, Status } from '../../../../../../common/types/api';
|
||||
|
||||
import { SyncStatus } from '../../../../../common/types/connectors';
|
||||
import { FetchSyncJobsApiLogic } from '../../api/connector/fetch_sync_jobs_api_logic';
|
||||
import {
|
||||
ConnectorSyncJob,
|
||||
SyncStatus,
|
||||
TriggerMethod,
|
||||
} from '../../../../../../common/types/connectors';
|
||||
import { FetchSyncJobsApiLogic } from '../../../api/connector/fetch_sync_jobs_api_logic';
|
||||
|
||||
import { IndexViewLogic } from '../index_view_logic';
|
||||
|
||||
import { IndexViewLogic } from './index_view_logic';
|
||||
import { SyncJobView, SyncJobsViewLogic } from './sync_jobs_view_logic';
|
||||
|
||||
// We can't test fetchTimeOutId because this will get set whenever the logic is created
|
||||
|
@ -54,21 +59,31 @@ describe('SyncJobsViewLogic', () => {
|
|||
|
||||
describe('actions', () => {
|
||||
describe('FetchIndexApiLogic.apiSuccess', () => {
|
||||
const syncJob = {
|
||||
const syncJob: ConnectorSyncJob = {
|
||||
canceled_at: null,
|
||||
cancelation_requested_at: null,
|
||||
completed_at: '2022-09-05T15:59:39.816+00:00',
|
||||
connector_id: 'we2284IBjobuR2-lAuXh',
|
||||
created_at: '2022-09-05T14:59:39.816+00:00',
|
||||
deleted_document_count: 20,
|
||||
error: null,
|
||||
filtering: null,
|
||||
id: 'id',
|
||||
index_name: 'indexName',
|
||||
indexed_document_count: 50,
|
||||
indexed_document_volume: 40,
|
||||
last_seen: '2022-09-05T15:59:39.816+00:00',
|
||||
metadata: {},
|
||||
pipeline: null,
|
||||
trigger_method: TriggerMethod.ON_DEMAND,
|
||||
started_at: '2022-09-05T14:59:39.816+00:00',
|
||||
status: SyncStatus.COMPLETED,
|
||||
worker_hostname: 'hostname_fake',
|
||||
};
|
||||
const syncJobView: SyncJobView = {
|
||||
docsCount: 30,
|
||||
...syncJob,
|
||||
duration: moment.duration(1, 'hour'),
|
||||
lastSync: syncJob.completed_at,
|
||||
lastSync: syncJob.completed_at ?? '',
|
||||
status: SyncStatus.COMPLETED,
|
||||
};
|
||||
it('should update values', async () => {
|
||||
|
@ -124,8 +139,10 @@ describe('SyncJobsViewLogic', () => {
|
|||
...DEFAULT_VALUES,
|
||||
syncJobs: [
|
||||
{
|
||||
docsCount: 50,
|
||||
duration: undefined,
|
||||
...syncJob,
|
||||
completed_at: null,
|
||||
deleted_document_count: 0,
|
||||
duration: expect.anything(),
|
||||
lastSync: syncJob.created_at,
|
||||
status: SyncStatus.IN_PROGRESS,
|
||||
},
|
|
@ -9,25 +9,23 @@ import { kea, MakeLogicType } from 'kea';
|
|||
|
||||
import moment from 'moment';
|
||||
|
||||
import { Status } from '../../../../../common/types/api';
|
||||
import { Status } from '../../../../../../common/types/api';
|
||||
|
||||
import { ConnectorSyncJob, SyncStatus } from '../../../../../common/types/connectors';
|
||||
import { Paginate } from '../../../../../common/types/pagination';
|
||||
import { Actions } from '../../../shared/api_logic/create_api_logic';
|
||||
import { clearFlashMessages, flashAPIErrors } from '../../../shared/flash_messages';
|
||||
import { ConnectorSyncJob } from '../../../../../../common/types/connectors';
|
||||
import { Paginate } from '../../../../../../common/types/pagination';
|
||||
import { Actions } from '../../../../shared/api_logic/create_api_logic';
|
||||
import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages';
|
||||
import {
|
||||
FetchSyncJobsApiLogic,
|
||||
FetchSyncJobsArgs,
|
||||
FetchSyncJobsResponse,
|
||||
} from '../../api/connector/fetch_sync_jobs_api_logic';
|
||||
} from '../../../api/connector/fetch_sync_jobs_api_logic';
|
||||
|
||||
import { IndexViewLogic } from './index_view_logic';
|
||||
import { IndexViewLogic } from '../index_view_logic';
|
||||
|
||||
export interface SyncJobView {
|
||||
docsCount: number;
|
||||
export interface SyncJobView extends ConnectorSyncJob {
|
||||
duration: moment.Duration;
|
||||
lastSync: string;
|
||||
status: SyncStatus;
|
||||
}
|
||||
|
||||
export interface IndexViewActions {
|
||||
|
@ -74,14 +72,13 @@ export const SyncJobsViewLogic = kea<MakeLogicType<IndexViewValues, IndexViewAct
|
|||
(data?: Paginate<ConnectorSyncJob>) =>
|
||||
data?.data.map((syncJob) => {
|
||||
return {
|
||||
docsCount: syncJob.deleted_document_count
|
||||
? syncJob.indexed_document_count - syncJob.deleted_document_count
|
||||
: syncJob.indexed_document_count,
|
||||
...syncJob,
|
||||
duration: syncJob.completed_at
|
||||
? moment.duration(moment(syncJob.completed_at).diff(moment(syncJob.created_at)))
|
||||
: syncJob.started_at
|
||||
? moment.duration(moment(new Date()).diff(moment(syncJob.started_at)))
|
||||
: undefined,
|
||||
lastSync: syncJob.completed_at ?? syncJob.created_at,
|
||||
status: syncJob.status,
|
||||
};
|
||||
}) ?? [],
|
||||
],
|
|
@ -135,10 +135,24 @@ export const IndicesTable: React.FC<IndicesTableProps> = ({
|
|||
{
|
||||
actions: [
|
||||
{
|
||||
description: 'View this index',
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.searchIndices.actions.viewIndex.title',
|
||||
{
|
||||
defaultMessage: 'View this index',
|
||||
}
|
||||
),
|
||||
icon: 'eye',
|
||||
isPrimary: false,
|
||||
name: (index) => `View ${index.name}`,
|
||||
name: (index) =>
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.content.searchIndices.actions.viewIndex.caption',
|
||||
{
|
||||
defaultMessage: 'View index {indexName}',
|
||||
values: {
|
||||
indexName: index.name,
|
||||
},
|
||||
}
|
||||
),
|
||||
onClick: (index) =>
|
||||
navigateToUrl(
|
||||
generateEncodedPath(SEARCH_INDEX_PATH, {
|
||||
|
@ -149,10 +163,24 @@ export const IndicesTable: React.FC<IndicesTableProps> = ({
|
|||
},
|
||||
{
|
||||
color: 'danger',
|
||||
description: 'Delete this index',
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.searchIndices.actions.deleteIndex.title',
|
||||
{
|
||||
defaultMessage: 'Delete this index',
|
||||
}
|
||||
),
|
||||
icon: 'trash',
|
||||
isPrimary: false,
|
||||
name: (index) => `Delete ${index.name}`,
|
||||
name: (index) =>
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.content.searchIndices.actions.deleteIndex.caption',
|
||||
{
|
||||
defaultMessage: 'Delete index {indexName}',
|
||||
values: {
|
||||
indexName: index.name,
|
||||
},
|
||||
}
|
||||
),
|
||||
onClick: (index) => onDelete(index),
|
||||
type: 'icon',
|
||||
},
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
export function dateToString(input?: string): string {
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
return moment(input).toLocaleString();
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { FilteringPolicy, FilteringRuleRule } from '../../../../common/types/connectors';
|
||||
|
||||
const filteringRuleStringMap: Record<FilteringRuleRule, string> = {
|
||||
[FilteringRuleRule.CONTAINS]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.contains',
|
||||
{
|
||||
defaultMessage: 'Contains',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.ENDS_WITH]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.endsWith',
|
||||
{
|
||||
defaultMessage: 'Ends with',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.EQUALS]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.equals',
|
||||
{
|
||||
defaultMessage: 'Equals',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.GT]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.greaterThan',
|
||||
{
|
||||
defaultMessage: 'Greater than',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.LT]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.lessThan',
|
||||
{
|
||||
defaultMessage: 'Less than',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.REGEX]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.regEx',
|
||||
{
|
||||
defaultMessage: 'Regular expression',
|
||||
}
|
||||
),
|
||||
[FilteringRuleRule.STARTS_WITH]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.rules.startsWith',
|
||||
{
|
||||
defaultMessage: 'Starts with',
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
export function filteringRuleToText(filteringRule: FilteringRuleRule): string {
|
||||
return filteringRuleStringMap[filteringRule];
|
||||
}
|
||||
|
||||
const filteringPolicyStringMap: Record<FilteringPolicy, string> = {
|
||||
[FilteringPolicy.EXCLUDE]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.policy.exclude',
|
||||
{
|
||||
defaultMessage: 'Exclude',
|
||||
}
|
||||
),
|
||||
[FilteringPolicy.INCLUDE]: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.filteringRules.policy.include',
|
||||
{
|
||||
defaultMessage: 'Include',
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
export function filteringPolicyToText(filteringPolicy: FilteringPolicy): string {
|
||||
return filteringPolicyStringMap[filteringPolicy];
|
||||
}
|
|
@ -49,7 +49,10 @@ export const fetchSyncJobsByConnectorId = async (
|
|||
const total = totalToPaginateTotal(result.hits.total);
|
||||
// If we get fewer results than the target page, make sure we return correct page we're on
|
||||
const resultPageIndex = Math.min(pageIndex, Math.trunc(total.total / size));
|
||||
const data = result.hits.hits.map((hit) => hit._source).filter(isNotNullish) ?? [];
|
||||
const data =
|
||||
result.hits.hits
|
||||
.map((hit) => (hit._source ? { ...hit._source, id: hit._id } : null))
|
||||
.filter(isNotNullish) ?? [];
|
||||
return {
|
||||
data,
|
||||
pageIndex: resultPageIndex,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue