[ML] Transform: Table enhancements (#69307)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Quynh Nguyen 2020-06-23 15:04:24 -05:00 committed by GitHub
parent b2d3833313
commit 1158be9264
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 92 additions and 381 deletions

View file

@ -14,10 +14,9 @@ export * from '../common/types/audit_message';
export * from '../common/util/anomaly_utils';
export * from '../common/util/errors';
export * from '../common/util/validators';
export * from './application/formatters/metric_change_description';
export * from './application/components/data_grid';
export * from './application/data_frame_analytics/common';
export * from './application/util/date_utils';

View file

@ -1,22 +0,0 @@
/*
* 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.
*/
// utility functions for handling dates
// @ts-ignore
import { formatDate } from '@elastic/eui/lib/services/format';
export function formatHumanReadableDate(ts: number) {
return formatDate(ts, 'MMMM Do YYYY');
}
export function formatHumanReadableDateTime(ts: number) {
return formatDate(ts, 'MMMM Do YYYY, HH:mm');
}
export function formatHumanReadableDateTimeSeconds(ts: number) {
return formatDate(ts, 'MMMM Do YYYY, HH:mm:ss');
}

View file

@ -54,6 +54,8 @@ export interface CreateRequestBody extends PreviewRequestBody {
export interface TransformPivotConfig extends CreateRequestBody {
id: TransformId;
create_time?: number;
version?: string;
}
export enum REFRESH_TRANSFORM_LIST_STATE {

View file

@ -10,8 +10,6 @@ import { TransformStats } from './transform_stats';
// Used to pass on attribute names to table columns
export enum TRANSFORM_LIST_COLUMN {
CONFIG_DEST_INDEX = 'config.dest.index',
CONFIG_SOURCE_INDEX = 'config.source.index',
DESCRIPTION = 'config.description',
ID = 'id',
}

View file

@ -54,7 +54,9 @@ export const useApi = () => {
});
},
getTransformsPreview(obj: PreviewRequestBody): Promise<GetTransformsResponse> {
return http.post(`${API_BASE_PATH}transforms/_preview`, { body: JSON.stringify(obj) });
return http.post(`${API_BASE_PATH}transforms/_preview`, {
body: JSON.stringify(obj),
});
},
startTransforms(
transformsInfo: TransformEndpointRequest[]

View file

@ -14,7 +14,7 @@ import { i18n } from '@kbn/i18n';
import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/common';
import { dictionaryToArray } from '../../../common/types/common';
import { formatHumanReadableDateTimeSeconds } from '../../../common/utils/date_utils';
import { formatHumanReadableDateTimeSeconds } from '../../shared_imports';
import { getNestedProperty } from '../../../common/utils/object_utils';
import {

View file

@ -1,291 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Transform: Transform List <ExpandedRow /> Minimal initialization 1`] = `
<EuiTabbedContent
autoFocus="initial"
expand={false}
initialSelectedTab={
Object {
"content": <ExpandedRowDetailsPane
sections={
Array [
Object {
"items": Array [
Object {
"description": "fq_date_histogram_1m_1441",
"title": "ID",
},
Object {
"description": "stopped",
"title": "state",
},
],
"position": "left",
"title": "State",
},
Object {
"items": Array [
Object {
"description": 1,
"title": "last.checkpoint",
},
Object {
"description": "July 29th 2019, 04:18:01",
"title": "last.timestamp",
},
Object {
"description": 1564388281199,
"title": "last.timestamp_millis",
},
],
"position": "left",
"title": "Checkpointing",
},
Object {
"items": Array [
Object {
"description": "16",
"title": "pages_processed",
},
Object {
"description": "86274",
"title": "documents_processed",
},
Object {
"description": "7200",
"title": "documents_indexed",
},
Object {
"description": "1",
"title": "trigger_count",
},
Object {
"description": "1310",
"title": "index_time_in_ms",
},
Object {
"description": "15",
"title": "index_total",
},
Object {
"description": "0",
"title": "index_failures",
},
Object {
"description": "463",
"title": "search_time_in_ms",
},
Object {
"description": "16",
"title": "search_total",
},
Object {
"description": "0",
"title": "search_failures",
},
],
"position": "right",
"title": "Stats",
},
]
}
/>,
"data-test-subj": "transformDetailsTab",
"id": "transform-details-tab-fq_date_histogram_1m_1441",
"name": "Transform details",
}
}
onTabClick={[Function]}
size="s"
style={
Object {
"width": "100%",
}
}
tabs={
Array [
Object {
"content": <ExpandedRowDetailsPane
sections={
Array [
Object {
"items": Array [
Object {
"description": "fq_date_histogram_1m_1441",
"title": "ID",
},
Object {
"description": "stopped",
"title": "state",
},
],
"position": "left",
"title": "State",
},
Object {
"items": Array [
Object {
"description": 1,
"title": "last.checkpoint",
},
Object {
"description": "July 29th 2019, 04:18:01",
"title": "last.timestamp",
},
Object {
"description": 1564388281199,
"title": "last.timestamp_millis",
},
],
"position": "left",
"title": "Checkpointing",
},
Object {
"items": Array [
Object {
"description": "16",
"title": "pages_processed",
},
Object {
"description": "86274",
"title": "documents_processed",
},
Object {
"description": "7200",
"title": "documents_indexed",
},
Object {
"description": "1",
"title": "trigger_count",
},
Object {
"description": "1310",
"title": "index_time_in_ms",
},
Object {
"description": "15",
"title": "index_total",
},
Object {
"description": "0",
"title": "index_failures",
},
Object {
"description": "463",
"title": "search_time_in_ms",
},
Object {
"description": "16",
"title": "search_total",
},
Object {
"description": "0",
"title": "search_failures",
},
],
"position": "right",
"title": "Stats",
},
]
}
/>,
"data-test-subj": "transformDetailsTab",
"id": "transform-details-tab-fq_date_histogram_1m_1441",
"name": "Transform details",
},
Object {
"content": <ExpandedRowJsonPane
json={
Object {
"create_time": 1564388146667,
"dest": Object {
"index": "fq_date_histogram_1m_1441",
},
"id": "fq_date_histogram_1m_1441",
"pivot": Object {
"aggregations": Object {
"responsetime.avg": Object {
"avg": Object {
"field": "responsetime",
},
},
},
"group_by": Object {
"@timestamp": Object {
"date_histogram": Object {
"calendar_interval": "1m",
"field": "@timestamp",
},
},
},
},
"source": Object {
"index": Array [
"farequote-2019",
],
"query": Object {
"match_all": Object {},
},
},
"version": "8.0.0",
}
}
/>,
"data-test-subj": "transformJsonTab",
"id": "transform-json-tab-fq_date_histogram_1m_1441",
"name": "JSON",
},
Object {
"content": <ExpandedRowMessagesPane
transformId="fq_date_histogram_1m_1441"
/>,
"data-test-subj": "transformMessagesTab",
"id": "transform-messages-tab-fq_date_histogram_1m_1441",
"name": "Messages",
},
Object {
"content": <ExpandedRowPreviewPane
transformConfig={
Object {
"create_time": 1564388146667,
"dest": Object {
"index": "fq_date_histogram_1m_1441",
},
"id": "fq_date_histogram_1m_1441",
"pivot": Object {
"aggregations": Object {
"responsetime.avg": Object {
"avg": Object {
"field": "responsetime",
},
},
},
"group_by": Object {
"@timestamp": Object {
"date_histogram": Object {
"calendar_interval": "1m",
"field": "@timestamp",
},
},
},
},
"source": Object {
"index": Array [
"farequote-2019",
],
"query": Object {
"match_all": Object {},
},
},
"version": "8.0.0",
}
}
/>,
"data-test-subj": "transformPreviewTab",
"id": "transform-preview-tab-fq_date_histogram_1m_1441",
"name": "Preview",
},
]
}
/>
`;

View file

@ -13,7 +13,6 @@ describe('Transform: Transform List Actions', () => {
const actions = getActions({ forceDisable: false });
expect(actions).toHaveLength(4);
expect(actions[0].isPrimary).toBeTruthy();
expect(typeof actions[0].render).toBe('function');
expect(typeof actions[1].render).toBe('function');
expect(typeof actions[2].render).toBe('function');

View file

@ -19,7 +19,6 @@ import { StopAction } from './action_stop';
export const getActions = ({ forceDisable }: { forceDisable: boolean }) => {
return [
{
isPrimary: true,
render: (item: TransformListRow) => {
if (item.stats.state === TRANSFORM_STATE.STOPPED) {
return <StartAction items={[item]} forceDisable={forceDisable} />;

View file

@ -12,15 +12,13 @@ describe('Transform: Job List Columns', () => {
test('getColumns()', () => {
const columns = getColumns([], () => {}, []);
expect(columns).toHaveLength(9);
expect(columns).toHaveLength(7);
expect(columns[0].isExpander).toBeTruthy();
expect(columns[1].name).toBe('ID');
expect(columns[2].name).toBe('Description');
expect(columns[3].name).toBe('Source index');
expect(columns[4].name).toBe('Destination index');
expect(columns[5].name).toBe('Status');
expect(columns[6].name).toBe('Mode');
expect(columns[7].name).toBe('Progress');
expect(columns[8].name).toBe('Actions');
expect(columns[3].name).toBe('Status');
expect(columns[4].name).toBe('Mode');
expect(columns[5].name).toBe('Progress');
expect(columns[6].name).toBe('Actions');
});
});

View file

@ -88,8 +88,6 @@ export const getColumns = (
EuiTableComputedColumnType<TransformListRow>,
EuiTableFieldDataColumnType<TransformListRow>,
EuiTableFieldDataColumnType<TransformListRow>,
EuiTableFieldDataColumnType<TransformListRow>,
EuiTableFieldDataColumnType<TransformListRow>,
EuiTableComputedColumnType<TransformListRow>,
EuiTableComputedColumnType<TransformListRow>,
EuiTableComputedColumnType<TransformListRow>,
@ -143,22 +141,6 @@ export const getColumns = (
sortable: true,
truncateText: true,
},
{
field: TRANSFORM_LIST_COLUMN.CONFIG_SOURCE_INDEX,
'data-test-subj': 'transformListColumnSourceIndex',
name: i18n.translate('xpack.transform.sourceIndex', { defaultMessage: 'Source index' }),
sortable: true,
truncateText: true,
},
{
field: TRANSFORM_LIST_COLUMN.CONFIG_DEST_INDEX,
'data-test-subj': 'transformListColumnDestinationIndex',
name: i18n.translate('xpack.transform.destinationIndex', {
defaultMessage: 'Destination index',
}),
sortable: true,
truncateText: true,
},
{
name: i18n.translate('xpack.transform.status', { defaultMessage: 'Status' }),
'data-test-subj': 'transformListColumnStatus',
@ -242,7 +224,7 @@ export const getColumns = (
{
name: i18n.translate('xpack.transform.tableActionLabel', { defaultMessage: 'Actions' }),
actions,
width: '200px',
width: '80px',
},
];

View file

@ -4,17 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { shallow } from 'enzyme';
import { render, fireEvent } from '@testing-library/react';
import React from 'react';
import moment from 'moment-timezone';
import { TransformListRow } from '../../../../common';
import { ExpandedRow } from './expanded_row';
import transformListRow from '../../../../common/__mocks__/transform_list_row.json';
import { within } from '@testing-library/dom';
jest.mock('../../../../../shared_imports');
jest.mock('../../../../../shared_imports', () => ({
formatHumanReadableDateTimeSeconds: jest.fn(),
}));
describe('Transform: Transform List <ExpandedRow />', () => {
// Set timezone to US/Eastern for consistent test results.
beforeEach(() => {
@ -25,11 +26,25 @@ describe('Transform: Transform List <ExpandedRow />', () => {
moment.tz.setDefault('Browser');
});
test('Minimal initialization', () => {
test('Minimal initialization', async () => {
const item: TransformListRow = transformListRow;
const wrapper = shallow(<ExpandedRow item={item} />);
const { getByText, getByTestId } = render(<ExpandedRow item={item} />);
expect(wrapper).toMatchSnapshot();
expect(getByText('Details')).toBeInTheDocument();
expect(getByText('Stats')).toBeInTheDocument();
expect(getByText('JSON')).toBeInTheDocument();
expect(getByText('Messages')).toBeInTheDocument();
expect(getByText('Preview')).toBeInTheDocument();
const tabContent = getByTestId('transformDetailsTabContent');
expect(tabContent).toBeInTheDocument();
expect(getByTestId('transformDetailsTab')).toHaveAttribute('aria-selected', 'true');
expect(within(tabContent).getByText('General')).toBeInTheDocument();
fireEvent.click(getByTestId('transformStatsTab'));
expect(getByTestId('transformStatsTab')).toHaveAttribute('aria-selected', 'true');
expect(within(tabContent).getByText('Stats')).toBeInTheDocument();
});
});

View file

@ -10,8 +10,8 @@ import { EuiTabbedContent } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { formatHumanReadableDateTimeSeconds } from '../../../../../../common/utils/date_utils';
import moment from 'moment-timezone';
import { formatHumanReadableDateTimeSeconds } from '../../../../../shared_imports';
import { TransformListRow } from '../../../../common';
import { ExpandedRowDetailsPane, SectionConfig } from './expanded_row_details_pane';
import { ExpandedRowJsonPane } from './expanded_row_json_pane';
@ -61,6 +61,44 @@ export const ExpandedRow: FC<Props> = ({ item }) => {
const state: SectionConfig = {
title: 'State',
items: stateItems,
position: 'right',
};
const configItems: Item[] = [
{
title: 'transform_id',
description: item.id,
},
{
title: 'transform_version',
description: item.config.version,
},
{
title: 'description',
description: item.config.description ?? '',
},
{
title: 'create_time',
description:
formatHumanReadableDateTimeSeconds(moment(item.config.create_time).unix() * 1000) ?? '',
},
{
title: 'source_index',
description: Array.isArray(item.config.source.index)
? item.config.source.index[0]
: item.config.source.index,
},
{
title: 'destination_index',
description: Array.isArray(item.config.dest.index)
? item.config.dest.index[0]
: item.config.dest.index,
},
];
const general: SectionConfig = {
title: 'General',
items: configItems,
position: 'left',
};
@ -108,7 +146,7 @@ export const ExpandedRow: FC<Props> = ({ item }) => {
const checkpointing: SectionConfig = {
title: 'Checkpointing',
items: checkpointingItems,
position: 'left',
position: 'right',
};
const stats: SectionConfig = {
@ -116,7 +154,7 @@ export const ExpandedRow: FC<Props> = ({ item }) => {
items: Object.entries(item.stats.stats).map((s) => {
return { title: s[0].toString(), description: getItemDescription(s[1]) };
}),
position: 'right',
position: 'left',
};
const tabs = [
@ -124,12 +162,23 @@ export const ExpandedRow: FC<Props> = ({ item }) => {
id: `transform-details-tab-${item.id}`,
'data-test-subj': 'transformDetailsTab',
name: i18n.translate(
'xpack.transform.transformList.transformDetails.tabs.transformSettingsLabel',
'xpack.transform.transformList.transformDetails.tabs.transformDetailsLabel',
{
defaultMessage: 'Transform details',
defaultMessage: 'Details',
}
),
content: <ExpandedRowDetailsPane sections={[state, checkpointing, stats]} />,
content: <ExpandedRowDetailsPane sections={[general, state, checkpointing]} />,
},
{
id: `transform-stats-tab-${item.id}`,
'data-test-subj': 'transformStatsTab',
name: i18n.translate(
'xpack.transform.transformList.transformDetails.tabs.transformStatsLabel',
{
defaultMessage: 'Stats',
}
),
content: <ExpandedRowDetailsPane sections={[stats]} />,
},
{
id: `transform-json-tab-${item.id}`,

View file

@ -17,6 +17,7 @@ export {
fetchChartsData,
getErrorMessage,
extractErrorMessage,
formatHumanReadableDateTimeSeconds,
getDataGridSchemaFromKibanaFieldType,
getFieldsFromKibanaIndexPattern,
multiColumnSortFactory,

View file

@ -15793,7 +15793,6 @@
"xpack.transform.cloneTransform.breadcrumbTitle": "クローン変換",
"xpack.transform.createTransform.breadcrumbTitle": "変換の作成",
"xpack.transform.description": "説明",
"xpack.transform.destinationIndex": "デスティネーションインデックス",
"xpack.transform.groupby.popoverForm.aggLabel": "集約",
"xpack.transform.groupBy.popoverForm.aggNameAlreadyUsedError": "別のグループ分けの構成が既にこの名前を使用しています。",
"xpack.transform.groupBy.popoverForm.aggNameInvalidCharError": "無効な名前です。「[」、「]」「>」は使用できず、名前の始めと終わりにはスペースを使用できません。",
@ -15828,7 +15827,6 @@
"xpack.transform.pivotPreview.PivotPreviewNoDataCalloutBody": "プレビューリクエストはデータを返しませんでした。オプションのクエリがデータを返し、グループ分け基準により使用されるフィールドと集約フィールドに値が存在することを確認してください。",
"xpack.transform.pivotPreview.PivotPreviewTitle": "ピボットプレビューを変換",
"xpack.transform.progress": "進捗",
"xpack.transform.sourceIndex": "ソースインデックス",
"xpack.transform.statsBar.batchTransformsLabel": "一斉",
"xpack.transform.statsBar.continuousTransformsLabel": "連続",
"xpack.transform.statsBar.failedTransformsLabel": "失敗",
@ -15989,7 +15987,6 @@
"xpack.transform.transformList.transformDetails.messagesPane.timeLabel": "時間",
"xpack.transform.transformList.transformDetails.tabs.transformMessagesLabel": "メッセージ",
"xpack.transform.transformList.transformDetails.tabs.transformPreviewLabel": "プレビュー",
"xpack.transform.transformList.transformDetails.tabs.transformSettingsLabel": "ジョブの詳細",
"xpack.transform.transformList.transformDocsLinkText": "変換ドキュメント",
"xpack.transform.transformList.transformTitle": "データフレームジョブ",
"xpack.transform.transformsDescription": "変換を使用して、集約されたインデックスまたはエンティティ中心のインデックスに、既存のElasticsearchインデックスをインデックスします。",

View file

@ -15798,7 +15798,6 @@
"xpack.transform.cloneTransform.breadcrumbTitle": "克隆转换",
"xpack.transform.createTransform.breadcrumbTitle": "创建转换",
"xpack.transform.description": "描述",
"xpack.transform.destinationIndex": "目标 IP",
"xpack.transform.groupby.popoverForm.aggLabel": "聚合",
"xpack.transform.groupBy.popoverForm.aggNameAlreadyUsedError": "其他分组依据配置已使用该名称。",
"xpack.transform.groupBy.popoverForm.aggNameInvalidCharError": "名称无效。不允许使用字符“[”、“]”和“>”,且名称不得以空格字符开头或结束。",
@ -15833,7 +15832,6 @@
"xpack.transform.pivotPreview.PivotPreviewNoDataCalloutBody": "预览请求未返回任何数据。请确保可选查询返回数据且存在分组依据和聚合字段使用的字段的值。",
"xpack.transform.pivotPreview.PivotPreviewTitle": "转换数据透视表预览",
"xpack.transform.progress": "进度",
"xpack.transform.sourceIndex": "源索引",
"xpack.transform.statsBar.batchTransformsLabel": "批量",
"xpack.transform.statsBar.continuousTransformsLabel": "连续",
"xpack.transform.statsBar.failedTransformsLabel": "失败",
@ -15994,7 +15992,6 @@
"xpack.transform.transformList.transformDetails.messagesPane.timeLabel": "时间",
"xpack.transform.transformList.transformDetails.tabs.transformMessagesLabel": "消息",
"xpack.transform.transformList.transformDetails.tabs.transformPreviewLabel": "预览",
"xpack.transform.transformList.transformDetails.tabs.transformSettingsLabel": "作业详情",
"xpack.transform.transformList.transformDocsLinkText": "转换文档",
"xpack.transform.transformList.transformTitle": "数据帧作业",
"xpack.transform.transformsDescription": "使用转换将现有 Elasticsearch 索引透视成摘要式或以实体为中心的索引。",

View file

@ -436,8 +436,6 @@ export default function ({ getService }: FtrProviderContext) {
await transform.table.assertTransformRowFields(testData.transformId, {
id: testData.transformId,
description: testData.transformDescription,
sourceIndex: testData.source,
destinationIndex: testData.destinationIndex,
status: testData.expected.row.status,
mode: testData.expected.row.mode,
progress: testData.expected.row.progress,

View file

@ -239,8 +239,6 @@ export default function ({ getService }: FtrProviderContext) {
await transform.table.assertTransformRowFields(testData.transformId, {
id: testData.transformId,
description: testData.transformDescription,
sourceIndex: testData.expected.sourceIndex,
destinationIndex: testData.destinationIndex,
status: testData.expected.row.status,
mode: testData.expected.row.mode,
progress: testData.expected.row.progress,

View file

@ -31,16 +31,6 @@ export function TransformTableProvider({ getService }: FtrProviderContext) {
.find('.euiTableCellContent')
.text()
.trim(),
sourceIndex: $tr
.findTestSubject('transformListColumnSourceIndex')
.find('.euiTableCellContent')
.text()
.trim(),
destinationIndex: $tr
.findTestSubject('transformListColumnDestinationIndex')
.find('.euiTableCellContent')
.text()
.trim(),
status: $tr
.findTestSubject('transformListColumnStatus')
.find('.euiTableCellContent')