[ML] Data Frames: Rename job to transform. (#41219) (#41324)

This PR renames directories and variables of occurrences of job in the context of data frames to transform across the code.
This commit is contained in:
Walter Rafelsberger 2019-07-17 11:51:18 +02:00 committed by GitHub
parent 630affedb9
commit 0344e92b16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
158 changed files with 1602 additions and 1461 deletions

View file

@ -29,11 +29,11 @@ export interface Privileges {
// File Data Visualizer
canFindFileStructure: boolean;
// Data Frames
canGetDataFrameJobs: boolean;
canDeleteDataFrameJob: boolean;
canPreviewDataFrameJob: boolean;
canCreateDataFrameJob: boolean;
canStartStopDataFrameJob: boolean;
canGetDataFrame: boolean;
canDeleteDataFrame: boolean;
canPreviewDataFrame: boolean;
canCreateDataFrame: boolean;
canStartStopDataFrame: boolean;
}
export function getDefaultPrivileges(): Privileges {
@ -61,10 +61,10 @@ export function getDefaultPrivileges(): Privileges {
// File Data Visualizer
canFindFileStructure: false,
// Data Frames
canGetDataFrameJobs: false,
canDeleteDataFrameJob: false,
canPreviewDataFrameJob: false,
canCreateDataFrameJob: false,
canStartStopDataFrameJob: false,
canGetDataFrame: false,
canDeleteDataFrame: false,
canPreviewDataFrame: false,
canCreateDataFrame: false,
canStartStopDataFrame: false,
};
}

View file

@ -1,3 +1,3 @@
@import 'components/aggregation_list/index';
@import 'components/group_by_list/index';
@import 'pages/job_management/components/job_list/index';
@import 'pages/data_frame_new_pivot/components/aggregation_list/index';
@import 'pages/data_frame_new_pivot/components/group_by_list/index';
@import 'pages/transform_management/components/transform_list/index';

View file

@ -4,4 +4,76 @@
* you may not use this file except in compliance with the Elastic License.
*/
export type FieldName = string;
import { Dictionary } from '../../../common/types/common';
export type EsId = string;
export type EsDocSource = Dictionary<any>;
export type EsFieldName = string;
export interface EsDoc extends Dictionary<any> {
_id: EsId;
_source: EsDocSource;
}
export const MAX_COLUMNS = 5;
export function getFlattenedFields(obj: EsDocSource): EsFieldName[] {
const flatDocFields: EsFieldName[] = [];
const newDocFields = Object.keys(obj);
newDocFields.forEach(f => {
const fieldValue = obj[f];
if (typeof fieldValue !== 'object' || fieldValue === null || Array.isArray(fieldValue)) {
flatDocFields.push(f);
} else {
const innerFields = getFlattenedFields(fieldValue);
const flattenedFields = innerFields.map(d => `${f}.${d}`);
flatDocFields.push(...flattenedFields);
}
});
return flatDocFields;
}
export const getSelectableFields = (docs: EsDoc[]): EsFieldName[] => {
if (docs.length === 0) {
return [];
}
const newDocFields = getFlattenedFields(docs[0]._source);
newDocFields.sort();
return newDocFields;
};
export const getDefaultSelectableFields = (docs: EsDoc[]): EsFieldName[] => {
if (docs.length === 0) {
return [];
}
const newDocFields = getFlattenedFields(docs[0]._source);
newDocFields.sort();
return newDocFields
.filter(k => {
let value = false;
docs.forEach(row => {
const source = row._source;
if (source[k] !== null) {
value = true;
}
});
return value;
})
.slice(0, MAX_COLUMNS);
};
export const toggleSelectedField = (
selectedFields: EsFieldName[],
column: EsFieldName
): EsFieldName[] => {
const index = selectedFields.indexOf(column);
if (index === -1) {
selectedFields.push(column);
} else {
selectedFields.splice(index, 1);
}
selectedFields.sort();
return selectedFields;
};

View file

@ -4,12 +4,82 @@
* you may not use this file except in compliance with the Elastic License.
*/
export * from './aggregations';
export * from './fields';
export * from './dropdown';
export * from './kibana_context';
export * from './job';
export * from './navigation';
export * from './pivot_aggs';
export * from './pivot_group_by';
export * from './request';
export { AggName, isAggName } from './aggregations';
export {
getDefaultSelectableFields,
getFlattenedFields,
getSelectableFields,
toggleSelectedField,
EsDoc,
EsDocSource,
EsFieldName,
MAX_COLUMNS,
} from './fields';
export { DropDownLabel, DropDownOption, Label } from './dropdown';
export {
KibanaContext,
KibanaContextValue,
isKibanaContext,
NullableKibanaContextValue,
SavedSearchQuery,
} from './kibana_context';
export {
isTransformIdValid,
refreshTransformList$,
useRefreshTransformList,
CreateRequestBody,
PreviewRequestBody,
DataFrameTransformId,
DataFrameTransformPivotConfig,
delayFormatRegex,
IndexName,
IndexPattern,
REFRESH_TRANSFORM_LIST_STATE,
} from './transform';
export { moveToDataFrameTransformList, moveToDataFrameWizard, moveToDiscover } from './navigation';
export {
getEsAggFromAggConfig,
isPivotAggsConfigWithUiSupport,
PivotAgg,
PivotAggDict,
PivotAggsConfig,
PivotAggsConfigDict,
PivotAggsConfigBase,
PivotAggsConfigWithUiSupport,
PivotAggsConfigWithUiSupportDict,
pivotAggsFieldSupport,
PIVOT_SUPPORTED_AGGS,
} from './pivot_aggs';
export {
dateHistogramIntervalFormatRegex,
getEsAggFromGroupByConfig,
histogramIntervalFormatRegex,
isPivotGroupByConfigWithUiSupport,
isGroupByDateHistogram,
isGroupByHistogram,
isGroupByTerms,
pivotGroupByFieldSupport,
DateHistogramAgg,
GenericAgg,
GroupByConfigWithInterval,
GroupByConfigWithUiSupport,
HistogramAgg,
PivotGroupBy,
PivotGroupByConfig,
PivotGroupByDict,
PivotGroupByConfigDict,
PivotGroupByConfigWithUiSupportDict,
PivotSupportedGroupByAggs,
PivotSupportedGroupByAggsWithInterval,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
TermsAgg,
} from './pivot_group_by';
export {
getPreviewRequestBody,
getCreateRequestBody,
getPivotQuery,
isDefaultQuery,
isSimpleQuery,
PivotQuery,
SimpleQuery,
} from './request';

View file

@ -9,10 +9,10 @@ import rison from 'rison-node';
import chrome from 'ui/chrome';
export function moveToDataFrameWizard() {
window.location.href = '#/data_frames/new_job';
window.location.href = '#/data_frames/new_transform';
}
export function moveToDataFrameJobsList() {
export function moveToDataFrameTransformList() {
window.location.href = '#/data_frames';
}

View file

@ -8,7 +8,7 @@ import { Dictionary } from '../../../common/types/common';
import { KBN_FIELD_TYPES } from '../../../common/constants/field_types';
import { AggName } from './aggregations';
import { FieldName } from './fields';
import { EsFieldName } from './fields';
export enum PIVOT_SUPPORTED_AGGS {
AVG = 'avg',
@ -19,15 +19,6 @@ export enum PIVOT_SUPPORTED_AGGS {
VALUE_COUNT = 'value_count',
}
export const pivotSupportedAggs: PIVOT_SUPPORTED_AGGS[] = [
PIVOT_SUPPORTED_AGGS.AVG,
PIVOT_SUPPORTED_AGGS.CARDINALITY,
PIVOT_SUPPORTED_AGGS.MAX,
PIVOT_SUPPORTED_AGGS.MIN,
PIVOT_SUPPORTED_AGGS.SUM,
PIVOT_SUPPORTED_AGGS.VALUE_COUNT,
];
export const pivotAggsFieldSupport = {
[KBN_FIELD_TYPES.ATTACHMENT]: [PIVOT_SUPPORTED_AGGS.VALUE_COUNT],
[KBN_FIELD_TYPES.BOOLEAN]: [PIVOT_SUPPORTED_AGGS.VALUE_COUNT],
@ -56,7 +47,7 @@ export const pivotAggsFieldSupport = {
export type PivotAgg = {
[key in PIVOT_SUPPORTED_AGGS]?: {
field: FieldName;
field: EsFieldName;
};
};
@ -70,7 +61,7 @@ export interface PivotAggsConfigBase {
}
export interface PivotAggsConfigWithUiSupport extends PivotAggsConfigBase {
field: FieldName;
field: EsFieldName;
}
export function isPivotAggsConfigWithUiSupport(arg: any): arg is PivotAggsConfigWithUiSupport {
@ -79,7 +70,7 @@ export function isPivotAggsConfigWithUiSupport(arg: any): arg is PivotAggsConfig
arg.hasOwnProperty('aggName') &&
arg.hasOwnProperty('dropDownName') &&
arg.hasOwnProperty('field') &&
pivotSupportedAggs.includes(arg.agg)
Object.values(PIVOT_SUPPORTED_AGGS).includes(arg.agg)
);
}

View file

@ -8,7 +8,7 @@ import { Dictionary } from '../../../common/types/common';
import { KBN_FIELD_TYPES } from '../../../common/constants/field_types';
import { AggName } from './aggregations';
import { FieldName } from './fields';
import { EsFieldName } from './fields';
export enum PIVOT_SUPPORTED_GROUP_BY_AGGS {
DATE_HISTOGRAM = 'date_histogram',
@ -16,16 +16,7 @@ export enum PIVOT_SUPPORTED_GROUP_BY_AGGS {
TERMS = 'terms',
}
export type PivotSupportedGroupByAggs =
| PIVOT_SUPPORTED_GROUP_BY_AGGS.DATE_HISTOGRAM
| PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM
| PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS;
export const pivotSupportedGroupByAggs: PivotSupportedGroupByAggs[] = [
PIVOT_SUPPORTED_GROUP_BY_AGGS.DATE_HISTOGRAM,
PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM,
PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS,
];
export type PivotSupportedGroupByAggs = PIVOT_SUPPORTED_GROUP_BY_AGGS;
export type PivotSupportedGroupByAggsWithInterval =
| PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM
@ -59,19 +50,19 @@ export const dateHistogramIntervalFormatRegex = /^[1-9][0-9]*(ms|s|m|h|d|w|M|q|y
interface GroupByDateHistogram extends GroupByConfigBase {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.DATE_HISTOGRAM;
field: FieldName;
field: EsFieldName;
calendar_interval: string;
}
interface GroupByHistogram extends GroupByConfigBase {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM;
field: FieldName;
field: EsFieldName;
interval: string;
}
interface GroupByTerms extends GroupByConfigBase {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS;
field: FieldName;
field: EsFieldName;
}
export type GroupByConfigWithInterval = GroupByDateHistogram | GroupByHistogram;
@ -119,20 +110,20 @@ export type GenericAgg = object;
export interface TermsAgg {
terms: {
field: FieldName;
field: EsFieldName;
};
}
export interface HistogramAgg {
histogram: {
field: FieldName;
field: EsFieldName;
interval: string;
};
}
export interface DateHistogramAgg {
date_histogram: {
field: FieldName;
field: EsFieldName;
calendar_interval: string;
};
}

View file

@ -6,14 +6,14 @@
import { PivotGroupByConfig } from '../common';
import { JobDetailsExposedState } from '../components/job_details/job_details_form';
import { DefinePivotExposedState } from '../components/define_pivot/define_pivot_form';
import { StepDefineExposedState } from '../pages/data_frame_new_pivot/components/step_define/step_define_form';
import { StepDetailsExposedState } from '../pages/data_frame_new_pivot/components/step_details/step_details_form';
import { PIVOT_SUPPORTED_GROUP_BY_AGGS } from './pivot_group_by';
import { PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from './pivot_aggs';
import {
getDataFramePreviewRequest,
getDataFrameRequest,
getPreviewRequestBody,
getCreateRequestBody,
getPivotQuery,
isDefaultQuery,
isSimpleQuery,
@ -48,7 +48,7 @@ describe('Data Frame: Common', () => {
});
});
test('getDataFramePreviewRequest()', () => {
test('getPreviewRequestBody()', () => {
const query = getPivotQuery('the-query');
const groupBy: PivotGroupByConfig[] = [
{
@ -66,7 +66,7 @@ describe('Data Frame: Common', () => {
dropDownName: 'the-agg-drop-down-name',
},
];
const request = getDataFramePreviewRequest('the-index-pattern-title', query, groupBy, aggs);
const request = getPreviewRequestBody('the-index-pattern-title', query, groupBy, aggs);
expect(request).toEqual({
pivot: {
@ -80,7 +80,7 @@ describe('Data Frame: Common', () => {
});
});
test('getDataFramePreviewRequest() with comma-separated index pattern', () => {
test('getPreviewRequestBody() with comma-separated index pattern', () => {
const query = getPivotQuery('the-query');
const groupBy: PivotGroupByConfig[] = [
{
@ -98,7 +98,7 @@ describe('Data Frame: Common', () => {
dropDownName: 'the-agg-drop-down-name',
},
];
const request = getDataFramePreviewRequest(
const request = getPreviewRequestBody(
'the-index-pattern-title,the-other-title',
query,
groupBy,
@ -117,7 +117,7 @@ describe('Data Frame: Common', () => {
});
});
test('getDataFrameRequest()', () => {
test('getCreateRequestBody()', () => {
const groupBy: PivotGroupByConfig = {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS,
field: 'the-group-by-field',
@ -130,29 +130,33 @@ describe('Data Frame: Common', () => {
aggName: 'the-agg-agg-name',
dropDownName: 'the-agg-drop-down-name',
};
const pivotState: DefinePivotExposedState = {
const pivotState: StepDefineExposedState = {
aggList: { 'the-agg-name': agg },
groupByList: { 'the-group-by-name': groupBy },
isAdvancedEditorEnabled: false,
search: 'the-query',
valid: true,
};
const jobDetailsState: JobDetailsExposedState = {
const transformDetailsState: StepDetailsExposedState = {
continuousModeDateField: 'the-continuous-mode-date-field',
continuousModeDelay: 'the-continuous-mode-delay',
createIndexPattern: false,
isContinuousModeEnabled: false,
jobId: 'the-job-id',
jobDescription: 'the-job-description',
transformId: 'the-transform-id',
transformDescription: 'the-transform-description',
destinationIndex: 'the-destination-index',
touched: true,
valid: true,
};
const request = getDataFrameRequest('the-index-pattern-title', pivotState, jobDetailsState);
const request = getCreateRequestBody(
'the-index-pattern-title',
pivotState,
transformDetailsState
);
expect(request).toEqual({
description: 'the-job-description',
description: 'the-transform-description',
dest: { index: 'the-destination-index' },
pivot: {
aggregations: { 'the-agg-agg-name': { avg: { field: 'the-agg-field' } } },

View file

@ -10,8 +10,8 @@ import { IndexPattern } from 'ui/index_patterns';
import { dictionaryToArray } from '../../../common/types/common';
import { DefinePivotExposedState } from '../components/define_pivot/define_pivot_form';
import { JobDetailsExposedState } from '../components/job_details/job_details_form';
import { StepDefineExposedState } from '../pages/data_frame_new_pivot/components/step_define/step_define_form';
import { StepDetailsExposedState } from '../pages/data_frame_new_pivot/components/step_details/step_details_form';
import {
getEsAggFromAggConfig,
@ -22,31 +22,10 @@ import {
PivotGroupByConfig,
} from '../common';
import { PivotAggDict, PivotAggsConfig } from './pivot_aggs';
import { DateHistogramAgg, HistogramAgg, PivotGroupByDict, TermsAgg } from './pivot_group_by';
import { PivotAggsConfig } from './pivot_aggs';
import { DateHistogramAgg, HistogramAgg, TermsAgg } from './pivot_group_by';
import { SavedSearchQuery } from './kibana_context';
import { IndexPattern as Index } from './job';
export interface DataFramePreviewRequest {
pivot: {
group_by: PivotGroupByDict;
aggregations: PivotAggDict;
};
source: {
index: Index | Index[];
query?: any;
};
}
export interface DataFrameRequest extends DataFramePreviewRequest {
dest: {
index: string;
};
}
export interface DataFrameJobConfig extends DataFrameRequest {
id: string;
}
import { PreviewRequestBody, CreateRequestBody } from './transform';
export interface SimpleQuery {
query_string: {
@ -78,15 +57,15 @@ export function isDefaultQuery(query: PivotQuery): boolean {
return isSimpleQuery(query) && query.query_string.query === '*';
}
export function getDataFramePreviewRequest(
export function getPreviewRequestBody(
indexPatternTitle: IndexPattern['title'],
query: PivotQuery,
groupBy: PivotGroupByConfig[],
aggs: PivotAggsConfig[]
): DataFramePreviewRequest {
): PreviewRequestBody {
const index = indexPatternTitle.split(',').map((name: string) => name.trim());
const request: DataFramePreviewRequest = {
const request: PreviewRequestBody = {
source: {
index,
},
@ -136,32 +115,32 @@ export function getDataFramePreviewRequest(
return request;
}
export function getDataFrameRequest(
export function getCreateRequestBody(
indexPatternTitle: IndexPattern['title'],
pivotState: DefinePivotExposedState,
jobDetailsState: JobDetailsExposedState
): DataFrameRequest {
const request: DataFrameRequest = {
...getDataFramePreviewRequest(
pivotState: StepDefineExposedState,
transformDetailsState: StepDetailsExposedState
): CreateRequestBody {
const request: CreateRequestBody = {
...getPreviewRequestBody(
indexPatternTitle,
getPivotQuery(pivotState.search),
dictionaryToArray(pivotState.groupByList),
dictionaryToArray(pivotState.aggList)
),
// conditionally add optional description
...(jobDetailsState.jobDescription !== ''
? { description: jobDetailsState.jobDescription }
...(transformDetailsState.transformDescription !== ''
? { description: transformDetailsState.transformDescription }
: {}),
dest: {
index: jobDetailsState.destinationIndex,
index: transformDetailsState.destinationIndex,
},
// conditionally add continuous mode config
...(jobDetailsState.isContinuousModeEnabled
...(transformDetailsState.isContinuousModeEnabled
? {
sync: {
time: {
field: jobDetailsState.continuousModeDateField,
delay: jobDetailsState.continuousModeDelay,
field: transformDetailsState.continuousModeDateField,
delay: transformDetailsState.continuousModeDelay,
},
},
}

View file

@ -9,20 +9,33 @@ import { BehaviorSubject } from 'rxjs';
import { filter, distinctUntilChanged } from 'rxjs/operators';
import { Subscription } from 'rxjs';
// @ts-ignore
import { isJobIdValid } from '../../../common/util/job_utils';
import { PivotAggDict } from './pivot_aggs';
import { PivotGroupByDict } from './pivot_group_by';
export const isTransformIdValid = isJobIdValid;
export type IndexName = string;
export type IndexPattern = string;
export type JobId = string;
export type DataFrameTransformId = string;
export interface DataFrameJob {
description?: string;
dest: {
index: IndexName;
export interface PreviewRequestBody {
pivot: {
group_by: PivotGroupByDict;
aggregations: PivotAggDict;
};
source: {
index: IndexPattern | IndexPattern[];
query?: any;
};
}
export interface CreateRequestBody extends PreviewRequestBody {
description?: string;
dest: {
index: IndexName;
};
sync?: {
time: {
@ -32,15 +45,8 @@ export interface DataFrameJob {
};
}
export interface DataFrameTransform extends DataFrameJob {
pivot: {
aggregations: PivotAggDict;
group_by: PivotGroupByDict;
};
}
export interface DataFrameTransformWithId extends DataFrameTransform {
id: string;
export interface DataFrameTransformPivotConfig extends CreateRequestBody {
id: DataFrameTransformId;
}
// Don't allow intervals of '0', don't allow floating intervals.

View file

@ -1,92 +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.
*/
import { Dictionary } from '../../../../common/types/common';
import { PivotQuery } from '../../common';
export type EsFieldName = string;
type EsId = string;
type EsDocSource = Dictionary<any>;
export interface EsDoc extends Dictionary<any> {
_id: EsId;
_source: EsDocSource;
}
export const MAX_COLUMNS = 5;
export function getFlattenedFields(obj: EsDocSource): EsFieldName[] {
const flatDocFields: EsFieldName[] = [];
const newDocFields = Object.keys(obj);
newDocFields.forEach(f => {
const fieldValue = obj[f];
if (typeof fieldValue !== 'object' || fieldValue === null || Array.isArray(fieldValue)) {
flatDocFields.push(f);
} else {
const innerFields = getFlattenedFields(fieldValue);
const flattenedFields = innerFields.map(d => `${f}.${d}`);
flatDocFields.push(...flattenedFields);
}
});
return flatDocFields;
}
export const getSelectableFields = (docs: EsDoc[]): EsFieldName[] => {
if (docs.length === 0) {
return [];
}
const newDocFields = getFlattenedFields(docs[0]._source);
newDocFields.sort();
return newDocFields;
};
export const getDefaultSelectableFields = (docs: EsDoc[]): EsFieldName[] => {
if (docs.length === 0) {
return [];
}
const newDocFields = getFlattenedFields(docs[0]._source);
newDocFields.sort();
return newDocFields
.filter(k => {
let value = false;
docs.forEach(row => {
const source = row._source;
if (source[k] !== null) {
value = true;
}
});
return value;
})
.slice(0, MAX_COLUMNS);
};
export const toggleSelectedField = (
selectedFields: EsFieldName[],
column: EsFieldName
): EsFieldName[] => {
const index = selectedFields.indexOf(column);
if (index === -1) {
selectedFields.push(column);
} else {
selectedFields.splice(index, 1);
}
selectedFields.sort();
return selectedFields;
};
export const getSourceIndexDevConsoleStatement = (query: PivotQuery, indexPatternTitle: string) => {
return `GET ${indexPatternTitle}/_search\n${JSON.stringify(
{
query,
},
null,
2
)}\n`;
};

View file

@ -6,7 +6,7 @@
import './pages/access_denied/directive';
import './pages/access_denied/route';
import './pages/job_management/directive';
import './pages/job_management/route';
import './pages/transform_management/directive';
import './pages/transform_management/route';
import './pages/data_frame_new_pivot/directive';
import './pages/data_frame_new_pivot/route';

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { DataFrameJobList } from './job_list';
export { DropDown } from './dropdown';

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { AggName, PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../common';
import { AggName, PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../../../common';
import { AggLabelForm } from './agg_label_form';

View file

@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n';
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/eui';
import { AggName, PivotAggsConfig, PivotAggsConfigWithUiSupportDict } from '../../common';
import { AggName, PivotAggsConfig, PivotAggsConfigWithUiSupportDict } from '../../../../common';
import { PopoverForm } from './popover_form';

View file

@ -0,0 +1,8 @@
/*
* 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.
*/
export { AggListForm, AggListProps } from './list_form';
export { AggListSummary, AggListSummaryProps } from './list_summary';

View file

@ -7,9 +7,9 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../common';
import { PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../../../common';
import { AggListForm, ListProps } from './list_form';
import { AggListForm, AggListProps } from './list_form';
describe('Data Frame: <AggListForm />', () => {
test('Minimal initialization', () => {
@ -19,7 +19,7 @@ describe('Data Frame: <AggListForm />', () => {
aggName: 'the-group-by-agg-name',
dropDownName: 'the-group-by-drop-down-name',
};
const props: ListProps = {
const props: AggListProps = {
list: { 'the-agg': item },
options: {},
deleteHandler() {},

View file

@ -13,18 +13,23 @@ import {
PivotAggsConfig,
PivotAggsConfigDict,
PivotAggsConfigWithUiSupportDict,
} from '../../common';
} from '../../../../common';
import { AggLabelForm } from './agg_label_form';
export interface ListProps {
export interface AggListProps {
list: PivotAggsConfigDict;
options: PivotAggsConfigWithUiSupportDict;
deleteHandler(l: string): void;
onChange(previousAggName: AggName, item: PivotAggsConfig): void;
}
export const AggListForm: React.SFC<ListProps> = ({ deleteHandler, list, onChange, options }) => {
export const AggListForm: React.SFC<AggListProps> = ({
deleteHandler,
list,
onChange,
options,
}) => {
const listKeys = Object.keys(list);
return (
<Fragment>

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../common';
import { PivotAggsConfig, PIVOT_SUPPORTED_AGGS } from '../../../../common';
import { AggListSummary, AggListSummaryProps } from './list_summary';

View file

@ -8,7 +8,7 @@ import React, { Fragment } from 'react';
import { EuiForm, EuiPanel, EuiSpacer } from '@elastic/eui';
import { AggName, PivotAggsConfigDict } from '../../common';
import { AggName, PivotAggsConfigDict } from '../../../../common';
export interface AggListSummaryProps {
list: PivotAggsConfigDict;

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { AggName, PIVOT_SUPPORTED_AGGS, PivotAggsConfig } from '../../common';
import { AggName, PIVOT_SUPPORTED_AGGS, PivotAggsConfig } from '../../../../common';
import { PopoverForm } from './popover_form';

View file

@ -17,7 +17,7 @@ import {
EuiSelect,
} from '@elastic/eui';
import { dictionaryToArray } from '../../../../common/types/common';
import { dictionaryToArray } from '../../../../../../common/types/common';
import {
AggName,
@ -27,7 +27,7 @@ import {
PivotAggsConfig,
PivotAggsConfigWithUiSupportDict,
PIVOT_SUPPORTED_AGGS,
} from '../../common';
} from '../../../../common';
interface SelectOption {
text: string;

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../common';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../../../common';
import { GroupByLabelForm } from './group_by_label_form';

View file

@ -16,7 +16,7 @@ import {
isGroupByHistogram,
PivotGroupByConfig,
PivotGroupByConfigWithUiSupportDict,
} from '../../common';
} from '../../../../common';
import { PopoverForm } from './popover_form';

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../common';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../../../common';
import { GroupByLabelSummary } from './group_by_label_summary';

View file

@ -8,7 +8,7 @@ import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui';
import { isGroupByDateHistogram, isGroupByHistogram, PivotGroupByConfig } from '../../common';
import { isGroupByDateHistogram, isGroupByHistogram, PivotGroupByConfig } from '../../../../common';
interface Props {
item: PivotGroupByConfig;

View file

@ -0,0 +1,8 @@
/*
* 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.
*/
export { GroupByListForm } from './list_form';
export { GroupByListSummary } from './list_summary';

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../common';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../../../common';
import { GroupByListForm } from './list_form';

View file

@ -13,7 +13,7 @@ import {
PivotGroupByConfig,
PivotGroupByConfigDict,
PivotGroupByConfigWithUiSupportDict,
} from '../../common';
} from '../../../../common';
import { GroupByLabelForm } from './group_by_label_form';

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../common';
import { PivotGroupByConfig, PIVOT_SUPPORTED_GROUP_BY_AGGS } from '../../../../common';
import { GroupByListSummary } from './list_summary';

View file

@ -8,7 +8,7 @@ import React, { Fragment } from 'react';
import { EuiPanel, EuiSpacer } from '@elastic/eui';
import { PivotGroupByConfigDict } from '../../common';
import { PivotGroupByConfigDict } from '../../../../common';
import { GroupByLabelSummary } from './group_by_label_summary';

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { AggName, PIVOT_SUPPORTED_GROUP_BY_AGGS, PivotGroupByConfig } from '../../common';
import { AggName, PIVOT_SUPPORTED_GROUP_BY_AGGS, PivotGroupByConfig } from '../../../../common';
import { isIntervalValid, PopoverForm } from './popover_form';

View file

@ -17,7 +17,7 @@ import {
EuiSelect,
} from '@elastic/eui';
import { dictionaryToArray } from '../../../../common/types/common';
import { dictionaryToArray } from '../../../../../../common/types/common';
import {
AggName,
@ -33,7 +33,7 @@ import {
PivotSupportedGroupByAggs,
PivotSupportedGroupByAggsWithInterval,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../common';
} from '../../../../common';
export function isIntervalValid(
interval: optionalInterval,

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { SimpleQuery } from '../../common';
import { SimpleQuery } from '../../../../common';
import { getSourceIndexDevConsoleStatement } from './common';

View file

@ -0,0 +1,17 @@
/*
* 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 { PivotQuery } from '../../../../common';
export const getSourceIndexDevConsoleStatement = (query: PivotQuery, indexPatternTitle: string) => {
return `GET ${indexPatternTitle}/_search\n${JSON.stringify(
{
query,
},
null,
2
)}\n`;
};

View file

@ -10,9 +10,7 @@ import React from 'react';
import { EuiBadge, EuiText } from '@elastic/eui';
import { EsDoc } from './common';
import { getSelectableFields } from './common';
import { getSelectableFields, EsDoc } from '../../../../common';
interface ExpandedRowProps {
item: EsDoc;

View file

@ -7,7 +7,7 @@
import { shallow } from 'enzyme';
import React from 'react';
import { getPivotQuery, KibanaContext } from '../../common';
import { getPivotQuery, KibanaContext } from '../../../../common';
import { SourceIndexPreview } from './source_index_preview';

View file

@ -39,19 +39,21 @@ interface ExpandableTableProps extends EuiInMemoryTableProps {
const ExpandableTable = (EuiInMemoryTable as any) as FunctionComponent<ExpandableTableProps>;
import { KBN_FIELD_TYPES } from '../../../../common/constants/field_types';
import { Dictionary } from '../../../../common/types/common';
import { formatHumanReadableDateTimeSeconds } from '../../../util/date_utils';
import { isKibanaContext, KibanaContext, PivotQuery } from '../../common';
import { KBN_FIELD_TYPES } from '../../../../../../common/constants/field_types';
import { Dictionary } from '../../../../../../common/types/common';
import { formatHumanReadableDateTimeSeconds } from '../../../../../util/date_utils';
import {
isKibanaContext,
toggleSelectedField,
EsDoc,
EsFieldName,
getSourceIndexDevConsoleStatement,
MAX_COLUMNS,
toggleSelectedField,
} from './common';
KibanaContext,
PivotQuery,
} from '../../../../common';
import { getSourceIndexDevConsoleStatement } from './common';
import { ExpandedRow } from './expanded_row';
import { SOURCE_INDEX_STATUS, useSourceIndexData } from './use_source_index_data';

View file

@ -8,15 +8,15 @@ import React, { SFC } from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import { ml } from '../../../services/ml_api_service';
import { SimpleQuery } from '../../common';
import { ml } from '../../../../../services/ml_api_service';
import { SimpleQuery } from '../../../../common';
import {
SOURCE_INDEX_STATUS,
useSourceIndexData,
UseSourceIndexDataReturnType,
} from './use_source_index_data';
jest.mock('../../../services/ml_api_service');
jest.mock('../../../../../services/ml_api_service');
type Callback = () => void;
interface TestHookProps {

View file

@ -12,10 +12,16 @@ import { SearchResponse } from 'elasticsearch';
import { IndexPattern } from 'ui/index_patterns';
import { ml } from '../../../services/ml_api_service';
import { ml } from '../../../../../services/ml_api_service';
import { isDefaultQuery, PivotQuery } from '../../common';
import { EsDoc, EsFieldName, getDefaultSelectableFields, getFlattenedFields } from './common';
import {
getDefaultSelectableFields,
getFlattenedFields,
isDefaultQuery,
EsDoc,
EsFieldName,
PivotQuery,
} from '../../../../common';
const SEARCH_SIZE = 1000;

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Data Frame: <JobCreateForm /> Minimal initialization 1`] = `
exports[`Data Frame: <StepCreateForm /> Minimal initialization 1`] = `
<div>
<ContextProvider
value={
@ -20,8 +20,6 @@ exports[`Data Frame: <JobCreateForm /> Minimal initialization 1`] = `
>
<Component
createIndexPattern={false}
jobConfig={Object {}}
jobId="the-job-id"
onChange={[Function]}
overrides={
Object {
@ -30,6 +28,8 @@ exports[`Data Frame: <JobCreateForm /> Minimal initialization 1`] = `
"started": false,
}
}
transformConfig={Object {}}
transformId="the-transform-id"
/>
</ContextProvider>
</div>

View file

@ -4,6 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { JobCreateForm, getDefaultJobCreateState } from './job_create_form';
export { JobCreateSummary } from './job_create_summary';
export { StepCreateForm, getDefaultStepCreateState } from './step_create_form';
export { StepCreateSummary } from './step_create_summary';

View file

@ -7,9 +7,9 @@
import { shallow } from 'enzyme';
import React from 'react';
import { KibanaContext } from '../../common';
import { KibanaContext } from '../../../../common';
import { JobCreateForm } from './job_create_form';
import { StepCreateForm } from './step_create_form';
// workaround to make React.memo() work with enzyme
jest.mock('react', () => {
@ -17,12 +17,12 @@ jest.mock('react', () => {
return { ...r, memo: (x: any) => x };
});
describe('Data Frame: <JobCreateForm />', () => {
describe('Data Frame: <StepCreateForm />', () => {
test('Minimal initialization', () => {
const props = {
createIndexPattern: false,
jobId: 'the-job-id',
jobConfig: {},
transformId: 'the-transform-id',
transformConfig: {},
overrides: { created: false, started: false, indexPatternId: undefined },
onChange() {},
};
@ -47,7 +47,7 @@ describe('Data Frame: <JobCreateForm />', () => {
kibanaConfig: {},
}}
>
<JobCreateForm {...props} />
<StepCreateForm {...props} />
</KibanaContext.Provider>
</div>
);

View file

@ -29,20 +29,23 @@ import {
EuiText,
} from '@elastic/eui';
import { ml } from '../../../services/ml_api_service';
import { PROGRESS_JOBS_REFRESH_INTERVAL_MS } from '../../../../common/constants/jobs_list';
import { ml } from '../../../../../services/ml_api_service';
import { PROGRESS_JOBS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants/jobs_list';
import { moveToDataFrameJobsList, moveToDiscover } from '../../common';
import {
isKibanaContext,
KibanaContext,
moveToDataFrameTransformList,
moveToDiscover,
} from '../../../../common';
import { KibanaContext, isKibanaContext } from '../../common';
export interface JobDetailsExposedState {
export interface StepDetailsExposedState {
created: boolean;
started: boolean;
indexPatternId: string | undefined;
}
export function getDefaultJobCreateState(): JobDetailsExposedState {
export function getDefaultStepCreateState(): StepDetailsExposedState {
return {
created: false,
started: false,
@ -52,15 +55,15 @@ export function getDefaultJobCreateState(): JobDetailsExposedState {
interface Props {
createIndexPattern: boolean;
jobId: string;
jobConfig: any;
overrides: JobDetailsExposedState;
onChange(s: JobDetailsExposedState): void;
transformId: string;
transformConfig: any;
overrides: StepDetailsExposedState;
onChange(s: StepDetailsExposedState): void;
}
export const JobCreateForm: SFC<Props> = React.memo(
({ createIndexPattern, jobConfig, jobId, onChange, overrides }) => {
const defaults = { ...getDefaultJobCreateState(), ...overrides };
export const StepCreateForm: SFC<Props> = React.memo(
({ createIndexPattern, transformConfig, transformId, onChange, overrides }) => {
const defaults = { ...getDefaultStepCreateState(), ...overrides };
const [created, setCreated] = useState(defaults.created);
const [started, setStarted] = useState(defaults.started);
@ -83,19 +86,20 @@ export const JobCreateForm: SFC<Props> = React.memo(
setCreated(true);
try {
await ml.dataFrame.createDataFrameTransformsJob(jobId, jobConfig);
await ml.dataFrame.createDataFrameTransform(transformId, transformConfig);
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobCreateForm.createJobSuccessMessage', {
defaultMessage: 'Data frame transform {jobId} created successfully.',
values: { jobId },
i18n.translate('xpack.ml.dataframe.stepCreateForm.createTransformSuccessMessage', {
defaultMessage: 'Data frame transform {transformId} created successfully.',
values: { transformId },
})
);
} catch (e) {
setCreated(false);
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobCreateForm.createJobErrorMessage', {
defaultMessage: 'An error occurred creating the data frame transform {jobId}: {error}',
values: { jobId, error: JSON.stringify(e) },
i18n.translate('xpack.ml.dataframe.stepCreateForm.createTransformErrorMessage', {
defaultMessage:
'An error occurred creating the data frame transform {transformId}: {error}',
values: { transformId, error: JSON.stringify(e) },
})
);
return false;
@ -112,19 +116,20 @@ export const JobCreateForm: SFC<Props> = React.memo(
setStarted(true);
try {
await ml.dataFrame.startDataFrameTransformsJob(jobId);
await ml.dataFrame.startDataFrameTransform(transformId);
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobCreateForm.startJobSuccessMessage', {
defaultMessage: 'Data frame transform {jobId} started successfully.',
values: { jobId },
i18n.translate('xpack.ml.dataframe.stepCreateForm.startTransformSuccessMessage', {
defaultMessage: 'Data frame transform {transformId} started successfully.',
values: { transformId },
})
);
} catch (e) {
setStarted(false);
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobCreateForm.startJobErrorMessage', {
defaultMessage: 'An error occurred starting the data frame transform {jobId}: {error}',
values: { jobId, error: JSON.stringify(e) },
i18n.translate('xpack.ml.dataframe.stepCreateForm.startTransformErrorMessage', {
defaultMessage:
'An error occurred starting the data frame transform {transformId}: {error}',
values: { transformId, error: JSON.stringify(e) },
})
);
}
@ -138,7 +143,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
}
const createKibanaIndexPattern = async () => {
const indexPatternName = jobConfig.dest.index;
const indexPatternName = transformConfig.dest.index;
try {
const newIndexPattern = await kibanaContext.indexPatterns.get();
@ -157,7 +162,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
}
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobCreateForm.reateIndexPatternSuccessMessage', {
i18n.translate('xpack.ml.dataframe.stepCreateForm.reateIndexPatternSuccessMessage', {
defaultMessage: 'Kibana index pattern {indexPatternName} created successfully.',
values: { indexPatternName },
})
@ -167,7 +172,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
return true;
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobCreateForm.createIndexPatternErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepCreateForm.createIndexPatternErrorMessage', {
defaultMessage:
'An error occurred creating the Kibana index pattern {indexPatternName}: {error}',
values: { indexPatternName, error: JSON.stringify(e) },
@ -177,14 +182,14 @@ export const JobCreateForm: SFC<Props> = React.memo(
}
};
const isBatchTransform = typeof jobConfig.sync === 'undefined';
const isBatchTransform = typeof transformConfig.sync === 'undefined';
if (started === true && progressPercentComplete === undefined && isBatchTransform) {
// wrapping in function so we can keep the interval id in local scope
function startProgressBar() {
const interval = setInterval(async () => {
try {
const stats = await ml.dataFrame.getDataFrameTransformsStats(jobId);
const stats = await ml.dataFrame.getDataFrameTransformsStats(transformId);
if (stats && Array.isArray(stats.transforms) && stats.transforms.length > 0) {
const percent = Math.round(stats.transforms[0].state.progress.percent_complete);
setProgressPercentComplete(percent);
@ -194,7 +199,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
}
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobCreateForm.progressErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepCreateForm.progressErrorMessage', {
defaultMessage: 'An error occurred getting the progress percentage: {error}',
values: { error: JSON.stringify(e) },
})
@ -208,8 +213,12 @@ export const JobCreateForm: SFC<Props> = React.memo(
startProgressBar();
}
function getJobConfigDevConsoleStatement() {
return `PUT _data_frame/transforms/${jobId}\n${JSON.stringify(jobConfig, null, 2)}\n\n`;
function getTransformConfigDevConsoleStatement() {
return `PUT _data_frame/transforms/${transformId}\n${JSON.stringify(
transformConfig,
null,
2
)}\n\n`;
}
// TODO move this to SASS
@ -223,7 +232,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexGroup alignItems="center" style={FLEX_GROUP_STYLE}>
<EuiFlexItem grow={false} style={FLEX_ITEM_STYLE}>
<EuiButton fill isDisabled={created && started} onClick={createAndStartDataFrame}>
{i18n.translate('xpack.ml.dataframe.jobCreateForm.createAndStartDataFrameButton', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.createAndStartDataFrameButton', {
defaultMessage: 'Create and start',
})}
</EuiButton>
@ -231,7 +240,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexItem>
<EuiText color="subdued" size="s">
{i18n.translate(
'xpack.ml.dataframe.jobCreateForm.createAndStartDataFrameDescription',
'xpack.ml.dataframe.stepCreateForm.createAndStartDataFrameDescription',
{
defaultMessage:
'Creates and starts the data frame transform. A data frame transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. After the transform is started, you will be offered options to continue exploring the data frame transform.',
@ -245,14 +254,14 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexGroup alignItems="center" style={FLEX_GROUP_STYLE}>
<EuiFlexItem grow={false} style={FLEX_ITEM_STYLE}>
<EuiButton fill isDisabled={created && started} onClick={startDataFrame}>
{i18n.translate('xpack.ml.dataframe.jobCreateForm.startDataFrameButton', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.startDataFrameButton', {
defaultMessage: 'Start',
})}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem>
<EuiText color="subdued" size="s">
{i18n.translate('xpack.ml.dataframe.jobCreateForm.startDataFrameDescription', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.startDataFrameDescription', {
defaultMessage:
'Starts the data frame transform. A data frame transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. After the transform is started, you will be offered options to continue exploring the data frame transform.',
})}
@ -263,14 +272,14 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexGroup alignItems="center" style={FLEX_GROUP_STYLE}>
<EuiFlexItem grow={false} style={FLEX_ITEM_STYLE}>
<EuiButton isDisabled={created} onClick={createDataFrame}>
{i18n.translate('xpack.ml.dataframe.jobCreateForm.createDataFrameButton', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.createDataFrameButton', {
defaultMessage: 'Create',
})}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem>
<EuiText color="subdued" size="s">
{i18n.translate('xpack.ml.dataframe.jobCreateForm.createDataFrameDescription', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.createDataFrameDescription', {
defaultMessage:
'Create the data frame transform without starting it. You will be able to start the transform later by returning to the data frame transforms list.',
})}
@ -279,11 +288,11 @@ export const JobCreateForm: SFC<Props> = React.memo(
</EuiFlexGroup>
<EuiFlexGroup alignItems="center" style={FLEX_GROUP_STYLE}>
<EuiFlexItem grow={false} style={FLEX_ITEM_STYLE}>
<EuiCopy textToCopy={getJobConfigDevConsoleStatement()}>
<EuiCopy textToCopy={getTransformConfigDevConsoleStatement()}>
{(copy: () => void) => (
<EuiButton onClick={copy} style={{ width: '100%' }}>
{i18n.translate(
'xpack.ml.dataframe.jobCreateForm.copyJobConfigToClipBoardButton',
'xpack.ml.dataframe.stepCreateForm.copyTransformConfigToClipboardButton',
{
defaultMessage: 'Copy to clipboard',
}
@ -295,7 +304,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexItem>
<EuiText color="subdued" size="s">
{i18n.translate(
'xpack.ml.dataframe.jobCreateForm.copyJobConfigToClipBoardDescription',
'xpack.ml.dataframe.stepCreateForm.copyTransformConfigToClipboardDescription',
{
defaultMessage:
'Copies to the clipboard the Kibana Dev Console command for creating the transform.',
@ -309,7 +318,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiSpacer size="m" />
<EuiText size="xs">
<strong>
{i18n.translate('xpack.ml.dataframe.jobCreateForm.progressTitle', {
{i18n.translate('xpack.ml.dataframe.stepCreateForm.progressTitle', {
defaultMessage: 'Progress',
})}
</strong>
@ -331,16 +340,19 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexItem style={PANEL_ITEM_STYLE}>
<EuiCard
icon={<EuiIcon size="xxl" type="list" />}
title={i18n.translate('xpack.ml.dataframe.jobCreateForm.jobsListCardTitle', {
defaultMessage: 'Data frame transforms',
})}
title={i18n.translate(
'xpack.ml.dataframe.stepCreateForm.transformListCardTitle',
{
defaultMessage: 'Data frame transforms',
}
)}
description={i18n.translate(
'xpack.ml.dataframe.jobCreateForm.jobManagementCardDescription',
'xpack.ml.dataframe.stepCreateForm.transformListCardDescription',
{
defaultMessage: 'Return to the data frame transform management page.',
}
)}
onClick={moveToDataFrameJobsList}
onClick={moveToDataFrameTransformList}
/>
</EuiFlexItem>
{started === true && createIndexPattern === true && indexPatternId === undefined && (
@ -350,7 +362,7 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiText color="subdued" size="s">
<p>
{i18n.translate(
'xpack.ml.dataframe.jobCreateForm.creatingIndexPatternMessage',
'xpack.ml.dataframe.stepCreateForm.creatingIndexPatternMessage',
{
defaultMessage: 'Creating Kibana index pattern ...',
}
@ -364,11 +376,11 @@ export const JobCreateForm: SFC<Props> = React.memo(
<EuiFlexItem style={PANEL_ITEM_STYLE}>
<EuiCard
icon={<EuiIcon size="xxl" type="discoverApp" />}
title={i18n.translate('xpack.ml.dataframe.jobCreateForm.discoverCardTitle', {
title={i18n.translate('xpack.ml.dataframe.stepCreateForm.discoverCardTitle', {
defaultMessage: 'Discover',
})}
description={i18n.translate(
'xpack.ml.dataframe.jobCreateForm.discoverCardDescription',
'xpack.ml.dataframe.stepCreateForm.discoverCardDescription',
{
defaultMessage: 'Use Discover to explore the data frame pivot.',
}

View file

@ -6,6 +6,6 @@
import React, { SFC } from 'react';
export const JobCreateSummary: SFC = React.memo(() => {
export const StepCreateSummary: SFC = React.memo(() => {
return null;
});

View file

@ -18,7 +18,7 @@ exports[`Data Frame: <DefinePivotSummary /> Minimal initialization 1`] = `
}
}
>
<DefinePivotSummary
<StepDefineSummary
aggList={
Object {
"the-agg-name": Object {

View file

@ -7,13 +7,13 @@
import { IndexPattern } from 'ui/index_patterns';
import {
getDataFramePreviewRequest,
getPreviewRequestBody,
PivotAggsConfig,
PivotGroupByConfig,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
SimpleQuery,
} from '../../common';
} from '../../../../common';
import { getPivotPreviewDevConsoleStatement, getPivotDropdownOptions } from './common';
@ -122,7 +122,7 @@ describe('Data Frame: Define Pivot Common', () => {
aggName: 'the-agg-agg-name',
dropDownName: 'the-agg-drop-down-name',
};
const request = getDataFramePreviewRequest('the-index-pattern-title', query, [groupBy], [agg]);
const request = getPreviewRequestBody('the-index-pattern-title', query, [groupBy], [agg]);
const pivotPreviewDevConsoleStatement = getPivotPreviewDevConsoleStatement(request);
expect(pivotPreviewDevConsoleStatement).toBe(`POST _data_frame/transforms/_preview

View file

@ -8,30 +8,30 @@ import { EuiComboBoxOptionProps } from '@elastic/eui';
import { IndexPattern } from 'ui/index_patterns';
import { KBN_FIELD_TYPES } from '../../../../common/constants/field_types';
import { KBN_FIELD_TYPES } from '../../../../../../common/constants/field_types';
import {
DataFramePreviewRequest,
PreviewRequestBody,
DropDownLabel,
DropDownOption,
FieldName,
EsFieldName,
GroupByConfigWithUiSupport,
PivotAggsConfigWithUiSupportDict,
pivotAggsFieldSupport,
PivotGroupByConfigWithUiSupportDict,
pivotGroupByFieldSupport,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../common';
} from '../../../../common';
export interface Field {
name: FieldName;
name: EsFieldName;
type: KBN_FIELD_TYPES;
}
function getDefaultGroupByConfig(
aggName: string,
dropDownName: string,
fieldName: FieldName,
fieldName: EsFieldName,
groupByAgg: PIVOT_SUPPORTED_GROUP_BY_AGGS
): GroupByConfigWithUiSupport {
switch (groupByAgg) {
@ -121,6 +121,6 @@ export function getPivotDropdownOptions(indexPattern: IndexPattern) {
};
}
export const getPivotPreviewDevConsoleStatement = (request: DataFramePreviewRequest) => {
export const getPivotPreviewDevConsoleStatement = (request: PreviewRequestBody) => {
return `POST _data_frame/transforms/_preview\n${JSON.stringify(request, null, 2)}\n`;
};

View file

@ -5,9 +5,8 @@
*/
export {
DefinePivotExposedState,
DefinePivotForm,
getDefaultPivotState,
} from './define_pivot_form';
export { DefinePivotSummary } from './define_pivot_summary';
StepDefineExposedState,
StepDefineForm,
getDefaultStepDefineState,
} from './step_define_form';
export { StepDefineSummary } from './step_define_summary';

View file

@ -14,7 +14,7 @@ import {
PivotGroupByConfig,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../common';
} from '../../../../common';
import { PivotPreview } from './pivot_preview';

View file

@ -24,21 +24,20 @@ import {
SortDirection,
} from '@elastic/eui';
import { Dictionary, dictionaryToArray } from '../../../../common/types/common';
import { ES_FIELD_TYPES } from '../../../../common/constants/field_types';
import { formatHumanReadableDateTimeSeconds } from '../../../util/date_utils';
import { Dictionary, dictionaryToArray } from '../../../../../../common/types/common';
import { ES_FIELD_TYPES } from '../../../../../../common/constants/field_types';
import { formatHumanReadableDateTimeSeconds } from '../../../../../util/date_utils';
import {
DataFramePreviewRequest,
getFlattenedFields,
isKibanaContext,
PreviewRequestBody,
KibanaContext,
PivotAggsConfigDict,
PivotGroupByConfig,
PivotGroupByConfigDict,
PivotQuery,
} from '../../common';
import { getFlattenedFields } from '../source_index_preview/common';
} from '../../../../common';
import { getPivotPreviewDevConsoleStatement } from './common';
import { PIVOT_PREVIEW_STATUS, usePivotPreviewData } from './use_pivot_preview_data';
@ -75,7 +74,7 @@ function usePrevious(value: any) {
}
interface PreviewTitleProps {
previewRequest: DataFramePreviewRequest;
previewRequest: PreviewRequestBody;
}
const PreviewTitle: SFC<PreviewTitleProps> = ({ previewRequest }) => {

View file

@ -13,8 +13,8 @@ import {
PivotGroupByConfigDict,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../common';
import { DefinePivotForm, isAggNameConflict } from './define_pivot_form';
} from '../../../../common';
import { StepDefineForm, isAggNameConflict } from './step_define_form';
// workaround to make React.memo() work with enzyme
jest.mock('react', () => {
@ -44,7 +44,7 @@ describe('Data Frame: <DefinePivotForm />', () => {
kibanaConfig: {},
}}
>
<DefinePivotForm onChange={() => {}} />
<StepDefineForm onChange={() => {}} />
</KibanaContext.Provider>
</div>
);

View file

@ -29,18 +29,18 @@ import {
EuiSwitch,
} from '@elastic/eui';
import { dictionaryToArray } from '../../../../common/types/common';
import { DropDown } from '../../components/aggregation_dropdown/dropdown';
import { AggListForm } from '../../components/aggregation_list';
import { GroupByListForm } from '../../components/group_by_list';
import { SourceIndexPreview } from '../../components/source_index_preview';
import { dictionaryToArray } from '../../../../../../common/types/common';
import { DropDown } from '../aggregation_dropdown';
import { AggListForm } from '../aggregation_list';
import { GroupByListForm } from '../group_by_list';
import { SourceIndexPreview } from '../source_index_preview';
import { PivotPreview } from './pivot_preview';
import {
AggName,
DropDownLabel,
getPivotQuery,
getDataFramePreviewRequest,
getPreviewRequestBody,
isKibanaContext,
KibanaContext,
KibanaContextValue,
@ -53,11 +53,11 @@ import {
PivotSupportedGroupByAggs,
PIVOT_SUPPORTED_AGGS,
SavedSearchQuery,
} from '../../common';
} from '../../../../common';
import { getPivotDropdownOptions } from './common';
export interface DefinePivotExposedState {
export interface StepDefineExposedState {
aggList: PivotAggsConfigDict;
groupByList: PivotGroupByConfigDict;
isAdvancedEditorEnabled: boolean;
@ -68,7 +68,9 @@ export interface DefinePivotExposedState {
const defaultSearch = '*';
const emptySearch = '';
export function getDefaultPivotState(kibanaContext: KibanaContextValue): DefinePivotExposedState {
export function getDefaultStepDefineState(
kibanaContext: KibanaContextValue
): StepDefineExposedState {
return {
aggList: {} as PivotAggsConfigDict,
groupByList: {} as PivotGroupByConfigDict,
@ -87,7 +89,7 @@ export function isAggNameConflict(
) {
if (aggList[aggName] !== undefined) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.definePivot.aggExistsErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepDefineForm.aggExistsErrorMessage', {
defaultMessage: `An aggregation configuration with the name '{aggName}' already exists.`,
values: { aggName },
})
@ -97,7 +99,7 @@ export function isAggNameConflict(
if (groupByList[aggName] !== undefined) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.definePivot.groupByExistsErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepDefineForm.groupByExistsErrorMessage', {
defaultMessage: `A group by configuration with the name '{aggName}' already exists.`,
values: { aggName },
})
@ -114,7 +116,7 @@ export function isAggNameConflict(
aggNameCheck = aggNameCheck === undefined ? aggNamePart : `${aggNameCheck}.${aggNamePart}`;
if (aggList[aggNameCheck] !== undefined || groupByList[aggNameCheck] !== undefined) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.definePivot.nestedConflictErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepDefineForm.nestedConflictErrorMessage', {
defaultMessage: `Couldn't add configuration '{aggName}' because of a nesting conflict with '{aggNameCheck}'.`,
values: { aggName, aggNameCheck },
})
@ -136,7 +138,7 @@ export function isAggNameConflict(
aggListNameCheck === undefined ? aggListNamePart : `${aggListNameCheck}.${aggListNamePart}`;
if (aggListNameCheck === aggName) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.definePivot.nestedAggListConflictErrorMessage', {
i18n.translate('xpack.ml.dataframe.stepDefineForm.nestedAggListConflictErrorMessage', {
defaultMessage: `Couldn't add configuration '{aggName}' because of a nesting conflict with '{aggListName}'.`,
values: { aggName, aggListName },
})
@ -162,10 +164,13 @@ export function isAggNameConflict(
: `${groupByListNameCheck}.${groupByListNamePart}`;
if (groupByListNameCheck === aggName) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.definePivot.nestedGroupByListConflictErrorMessage', {
defaultMessage: `Couldn't add configuration '{aggName}' because of a nesting conflict with '{groupByListName}'.`,
values: { aggName, groupByListName },
})
i18n.translate(
'xpack.ml.dataframe.stepDefineForm.nestedGroupByListConflictErrorMessage',
{
defaultMessage: `Couldn't add configuration '{aggName}' because of a nesting conflict with '{groupByListName}'.`,
values: { aggName, groupByListName },
}
)
);
return true;
}
@ -177,11 +182,11 @@ export function isAggNameConflict(
}
interface Props {
overrides?: DefinePivotExposedState;
onChange(s: DefinePivotExposedState): void;
overrides?: StepDefineExposedState;
onChange(s: StepDefineExposedState): void;
}
export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChange }) => {
export const StepDefineForm: SFC<Props> = React.memo(({ overrides = {}, onChange }) => {
const kibanaContext = useContext(KibanaContext);
if (!isKibanaContext(kibanaContext)) {
@ -190,7 +195,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
const indexPattern = kibanaContext.currentIndexPattern;
const defaults = { ...getDefaultPivotState(kibanaContext), ...overrides };
const defaults = { ...getDefaultStepDefineState(kibanaContext), ...overrides };
// The search filter
const [search, setSearch] = useState(defaults.search);
@ -289,7 +294,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
defaults.isAdvancedEditorEnabled
);
const previewRequest = getDataFramePreviewRequest(
const previewRequest = getPreviewRequestBody(
indexPattern.title,
pivotQuery,
pivotGroupByArr,
@ -357,12 +362,12 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
const docsUrl = `https://www.elastic.co/guide/en/elasticsearch/reference/${metadata.branch}/data-frame-transform-pivot.html`;
const advancedEditorHelpText = (
<Fragment>
{i18n.translate('xpack.ml.dataframe.definePivotForm.advancedEditorHelpText', {
{i18n.translate('xpack.ml.dataframe.stepDefineForm.advancedEditorHelpText', {
defaultMessage:
'The advanced editor allows you to edit the pivot configuration of the data frame transform.',
})}{' '}
<EuiLink href={docsUrl} target="_blank">
{i18n.translate('xpack.ml.dataframe.definePivotForm.advancedEditorHelpTextLink', {
{i18n.translate('xpack.ml.dataframe.stepDefineForm.advancedEditorHelpTextLink', {
defaultMessage: 'Learn more about available options.',
})}
</EuiLink>
@ -372,7 +377,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
const valid = pivotGroupByArr.length > 0 && pivotAggsArr.length > 0;
useEffect(() => {
const previewRequestUpdate = getDataFramePreviewRequest(
const previewRequestUpdate = getPreviewRequestBody(
indexPattern.title,
pivotQuery,
pivotGroupByArr,
@ -409,12 +414,12 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
{kibanaContext.currentSavedSearch.id === undefined && typeof search === 'string' && (
<Fragment>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.indexPatternLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.indexPatternLabel', {
defaultMessage: 'Index pattern',
})}
helpText={
disabledQuery
? i18n.translate('xpack.ml.dataframe.definePivotForm.indexPatternHelpText', {
? i18n.translate('xpack.ml.dataframe.stepDefineForm.indexPatternHelpText', {
defaultMessage:
'An optional query for this index pattern is not supported. The number of supported index fields is {maxIndexFields} whereas this index has {numIndexFields} fields.',
values: {
@ -429,10 +434,10 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
</EuiFormRow>
{!disabledQuery && (
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.queryLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.queryLabel', {
defaultMessage: 'Query',
})}
helpText={i18n.translate('xpack.ml.dataframe.definePivotForm.queryHelpText', {
helpText={i18n.translate('xpack.ml.dataframe.stepDefineForm.queryHelpText', {
defaultMessage: 'Use a query string to filter the source data (optional).',
})}
>
@ -440,7 +445,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
defaultQuery={search === defaultSearch ? emptySearch : search}
box={{
placeholder: i18n.translate(
'xpack.ml.dataframe.definePivotForm.queryPlaceholder',
'xpack.ml.dataframe.stepDefineForm.queryPlaceholder',
{
defaultMessage: 'e.g. {example}',
values: { example: 'method:GET -is:active' },
@ -457,7 +462,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
{kibanaContext.currentSavedSearch.id !== undefined && (
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.savedSearchLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.savedSearchLabel', {
defaultMessage: 'Saved search',
})}
>
@ -468,7 +473,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
{!isAdvancedEditorEnabled && (
<Fragment>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.groupByLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.groupByLabel', {
defaultMessage: 'Group by',
})}
>
@ -483,7 +488,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
changeHandler={addGroupBy}
options={groupByOptions}
placeholder={i18n.translate(
'xpack.ml.dataframe.definePivotForm.groupByPlaceholder',
'xpack.ml.dataframe.stepDefineForm.groupByPlaceholder',
{
defaultMessage: 'Add a group by field ...',
}
@ -493,7 +498,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.aggregationsLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.aggregationsLabel', {
defaultMessage: 'Aggregations',
})}
>
@ -508,7 +513,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
changeHandler={addAggregation}
options={aggOptions}
placeholder={i18n.translate(
'xpack.ml.dataframe.definePivotForm.aggregationsPlaceholder',
'xpack.ml.dataframe.stepDefineForm.aggregationsPlaceholder',
{
defaultMessage: 'Add an aggregation ...',
}
@ -522,7 +527,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
{isAdvancedEditorEnabled && (
<Fragment>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.advancedEditorLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineForm.advancedEditorLabel', {
defaultMessage: 'Pivot configuration object',
})}
helpText={advancedEditorHelpText}
@ -554,7 +559,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
fontSize: '12px',
}}
aria-label={i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorAriaLabel',
'xpack.ml.dataframe.stepDefineForm.advancedEditorAriaLabel',
{
defaultMessage: 'Advanced editor',
}
@ -569,7 +574,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
<EuiFlexItem>
<EuiSwitch
label={i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorSwitchLabel',
'xpack.ml.dataframe.stepDefineForm.advancedEditorSwitchLabel',
{
defaultMessage: 'Advanced editor',
}
@ -592,7 +597,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
<EuiOverlayMask>
<EuiConfirmModal
title={i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorSwitchModalTitle',
'xpack.ml.dataframe.stepDefineForm.advancedEditorSwitchModalTitle',
{
defaultMessage: 'Unapplied changes',
}
@ -603,13 +608,13 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
toggleAdvancedEditor();
}}
cancelButtonText={i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorSwitchModalCancelButtonText',
'xpack.ml.dataframe.stepDefineForm.advancedEditorSwitchModalCancelButtonText',
{
defaultMessage: 'Cancel',
}
)}
confirmButtonText={i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorSwitchModalConfirmButtonText',
'xpack.ml.dataframe.stepDefineForm.advancedEditorSwitchModalConfirmButtonText',
{
defaultMessage: 'Disable advanced editor',
}
@ -619,7 +624,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
>
<p>
{i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorSwitchModalBodyText',
'xpack.ml.dataframe.stepDefineForm.advancedEditorSwitchModalBodyText',
{
defaultMessage: `The changes in the advanced editor haven't been applied yet. By disabling the advanced editor you will lose your edits.`,
}
@ -637,7 +642,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
disabled={!isAdvancedEditorApplyButtonEnabled}
>
{i18n.translate(
'xpack.ml.dataframe.definePivotForm.advancedEditorApplyButtonText',
'xpack.ml.dataframe.stepDefineForm.advancedEditorApplyButtonText',
{
defaultMessage: 'Apply changes',
}
@ -649,7 +654,7 @@ export const DefinePivotForm: SFC<Props> = React.memo(({ overrides = {}, onChang
{!valid && (
<Fragment>
<EuiFormHelpText style={{ maxWidth: '320px' }}>
{i18n.translate('xpack.ml.dataframe.definePivotForm.formHelp', {
{i18n.translate('xpack.ml.dataframe.stepDefineForm.formHelp', {
defaultMessage:
'Data frame transforms are scalable and automated processes for pivoting. Choose at least one group-by and aggregation to get started.',
})}

View file

@ -13,10 +13,10 @@ import {
PivotGroupByConfig,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../common';
} from '../../../../common';
import { DefinePivotExposedState } from './define_pivot_form';
import { DefinePivotSummary } from './define_pivot_summary';
import { StepDefineExposedState } from './step_define_form';
import { StepDefineSummary } from './step_define_summary';
// workaround to make React.memo() work with enzyme
jest.mock('react', () => {
@ -44,7 +44,7 @@ describe('Data Frame: <DefinePivotSummary />', () => {
aggName: 'the-group-by-agg-name',
dropDownName: 'the-group-by-drop-down-name',
};
const props: DefinePivotExposedState = {
const props: StepDefineExposedState = {
aggList: { 'the-agg-name': agg },
groupByList: { 'the-group-by-name': groupBy },
isAdvancedEditorEnabled: false,
@ -66,7 +66,7 @@ describe('Data Frame: <DefinePivotSummary />', () => {
kibanaConfig: {},
}}
>
<DefinePivotSummary {...props} />
<StepDefineSummary {...props} />
</KibanaContext.Provider>
</div>
);

View file

@ -10,17 +10,17 @@ import { i18n } from '@kbn/i18n';
import { EuiFlexGroup, EuiFlexItem, EuiForm, EuiFormRow, EuiText } from '@elastic/eui';
import { AggListSummary } from '../../components/aggregation_list';
import { GroupByListSummary } from '../../components/group_by_list';
import { AggListSummary } from '../aggregation_list';
import { GroupByListSummary } from '../group_by_list';
import { PivotPreview } from './pivot_preview';
import { getPivotQuery, isKibanaContext, KibanaContext } from '../../common';
import { DefinePivotExposedState } from './define_pivot_form';
import { getPivotQuery, isKibanaContext, KibanaContext } from '../../../../common';
import { StepDefineExposedState } from './step_define_form';
const defaultSearch = '*';
const emptySearch = '';
export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
export const StepDefineSummary: SFC<StepDefineExposedState> = ({
search,
groupByList,
aggList,
@ -42,7 +42,7 @@ export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
{kibanaContext.currentSavedSearch.id === undefined && typeof search === 'string' && (
<Fragment>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotSummary.indexPatternLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineSummary.indexPatternLabel', {
defaultMessage: 'Index pattern',
})}
>
@ -50,7 +50,7 @@ export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
</EuiFormRow>
{displaySearch !== emptySearch && (
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotSummary.queryLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineSummary.queryLabel', {
defaultMessage: 'Query',
})}
>
@ -62,7 +62,7 @@ export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
{kibanaContext.currentSavedSearch.id !== undefined && (
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotForm.savedSearchLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineSummary.savedSearchLabel', {
defaultMessage: 'Saved search',
})}
>
@ -71,7 +71,7 @@ export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
)}
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotSummary.groupByLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineSummary.groupByLabel', {
defaultMessage: 'Group by',
})}
>
@ -79,7 +79,7 @@ export const DefinePivotSummary: SFC<DefinePivotExposedState> = ({
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.definePivotSummary.aggregationsLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDefineSummary.aggregationsLabel', {
defaultMessage: 'Aggregations',
})}
>

View file

@ -7,15 +7,15 @@
import React, { SFC } from 'react';
import ReactDOM from 'react-dom';
import { ml } from '../../../services/ml_api_service';
import { SimpleQuery } from '../../common';
import { ml } from '../../../../../services/ml_api_service';
import { SimpleQuery } from '../../../../common';
import {
PIVOT_PREVIEW_STATUS,
usePivotPreviewData,
UsePivotPreviewDataReturnType,
} from './use_pivot_preview_data';
jest.mock('../../../services/ml_api_service');
jest.mock('../../../../../services/ml_api_service');
type Callback = () => void;
interface TestHookProps {

View file

@ -8,18 +8,18 @@ import { useEffect, useState } from 'react';
import { IndexPattern } from 'ui/index_patterns';
import { dictionaryToArray } from '../../../../common/types/common';
import { ml } from '../../../services/ml_api_service';
import { dictionaryToArray } from '../../../../../../common/types/common';
import { ml } from '../../../../../services/ml_api_service';
import { Dictionary } from '../../../../common/types/common';
import { ES_FIELD_TYPES } from '../../../../common/constants/field_types';
import { Dictionary } from '../../../../../../common/types/common';
import { ES_FIELD_TYPES } from '../../../../../../common/constants/field_types';
import {
DataFramePreviewRequest,
getDataFramePreviewRequest,
getPreviewRequestBody,
PreviewRequestBody,
PivotAggsConfigDict,
PivotGroupByConfigDict,
PivotQuery,
} from '../../common';
} from '../../../../common';
export enum PIVOT_PREVIEW_STATUS {
UNUSED,
@ -42,7 +42,7 @@ export interface UsePivotPreviewDataReturnType {
status: PIVOT_PREVIEW_STATUS;
dataFramePreviewData: DataFramePreviewData;
dataFramePreviewMappings: DataFramePreviewMappings;
previewRequest: DataFramePreviewRequest;
previewRequest: PreviewRequestBody;
}
export interface GetDataFrameTransformsResponse {
@ -66,7 +66,7 @@ export const usePivotPreviewData = (
const aggsArr = dictionaryToArray(aggs);
const groupByArr = dictionaryToArray(groupBy);
const previewRequest = getDataFramePreviewRequest(indexPattern.title, query, groupByArr, aggsArr);
const previewRequest = getPreviewRequestBody(indexPattern.title, query, groupByArr, aggsArr);
const getDataFramePreviewData = async () => {
if (aggsArr.length === 0 || groupByArr.length === 0) {

View file

@ -4,6 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
export type JobId = string;
export type EsIndexName = string;
export type IndexPatternTitle = string;

View file

@ -4,6 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { JobDetailsForm, getDefaultJobDetailsState } from './job_details_form';
export { JobDetailsSummary } from './job_details_summary';
export { StepDetailsForm, getDefaultStepDetailsState } from './step_details_form';
export { StepDetailsSummary } from './step_details_summary';

View file

@ -12,35 +12,40 @@ import { toastNotifications } from 'ui/notify';
import { EuiLink, EuiSwitch, EuiFieldText, EuiForm, EuiFormRow, EuiSelect } from '@elastic/eui';
// @ts-ignore
import { isJobIdValid } from '../../../../common/util/job_utils';
import { isValidIndexName } from '../../../../common/util/es_utils';
import { isValidIndexName } from '../../../../../../common/util/es_utils';
import { ml } from '../../../services/ml_api_service';
import { ml } from '../../../../../services/ml_api_service';
import { DataFrameJobConfig, delayFormatRegex, KibanaContext, isKibanaContext } from '../../common';
import { EsIndexName, IndexPatternTitle, JobId } from './common';
import {
delayFormatRegex,
isKibanaContext,
isTransformIdValid,
DataFrameTransformId,
DataFrameTransformPivotConfig,
KibanaContext,
} from '../../../../common';
import { EsIndexName, IndexPatternTitle } from './common';
export interface JobDetailsExposedState {
export interface StepDetailsExposedState {
continuousModeDateField: string;
continuousModeDelay: string;
createIndexPattern: boolean;
isContinuousModeEnabled: boolean;
jobId: JobId;
jobDescription: string;
destinationIndex: EsIndexName;
isContinuousModeEnabled: boolean;
touched: boolean;
transformId: DataFrameTransformId;
transformDescription: string;
valid: boolean;
}
export function getDefaultJobDetailsState(): JobDetailsExposedState {
export function getDefaultStepDetailsState(): StepDetailsExposedState {
return {
continuousModeDateField: '',
continuousModeDelay: '60s',
createIndexPattern: true,
isContinuousModeEnabled: false,
jobId: '',
jobDescription: '',
transformId: '',
transformDescription: '',
destinationIndex: '',
touched: false,
valid: false,
@ -48,23 +53,25 @@ export function getDefaultJobDetailsState(): JobDetailsExposedState {
}
interface Props {
overrides?: JobDetailsExposedState;
onChange(s: JobDetailsExposedState): void;
overrides?: StepDetailsExposedState;
onChange(s: StepDetailsExposedState): void;
}
export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange }) => {
export const StepDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange }) => {
const kibanaContext = useContext(KibanaContext);
if (!isKibanaContext(kibanaContext)) {
return null;
}
const defaults = { ...getDefaultJobDetailsState(), ...overrides };
const defaults = { ...getDefaultStepDetailsState(), ...overrides };
const [jobId, setJobId] = useState<JobId>(defaults.jobId);
const [jobDescription, setJobDescription] = useState<string>(defaults.jobDescription);
const [transformId, setTransformId] = useState<DataFrameTransformId>(defaults.transformId);
const [transformDescription, setTransformDescription] = useState<string>(
defaults.transformDescription
);
const [destinationIndex, setDestinationIndex] = useState<EsIndexName>(defaults.destinationIndex);
const [jobIds, setJobIds] = useState<JobId[]>([]);
const [transformIds, setTransformIds] = useState<DataFrameTransformId[]>([]);
const [indexNames, setIndexNames] = useState<EsIndexName[]>([]);
const [indexPatternTitles, setIndexPatternTitles] = useState<IndexPatternTitle[]>([]);
const [createIndexPattern, setCreateIndexPattern] = useState(defaults.createIndexPattern);
@ -84,19 +91,19 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
const [continuousModeDelay, setContinuousModeDelay] = useState(defaults.continuousModeDelay);
const isContinuousModeDelayValid = continuousModeDelay.match(delayFormatRegex) !== null;
// fetch existing job IDs and indices once for form validation
// fetch existing transform IDs and indices once for form validation
useEffect(() => {
// use an IIFE to avoid returning a Promise to useEffect.
(async function() {
try {
setJobIds(
setTransformIds(
(await ml.dataFrame.getDataFrameTransforms()).transforms.map(
(job: DataFrameJobConfig) => job.id
(transform: DataFrameTransformPivotConfig) => transform.id
)
);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobDetailsForm.errorGettingDataFrameJobsList', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.errorGettingDataFrameTransformList', {
defaultMessage:
'An error occurred getting the existing data frame transform Ids: {error}',
values: { error: JSON.stringify(e) },
@ -108,7 +115,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
setIndexNames((await ml.getIndices()).map(index => index.name));
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobDetailsForm.errorGettingDataFrameIndexNames', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.errorGettingDataFrameIndexNames', {
defaultMessage: 'An error occurred getting the existing index names: {error}',
values: { error: JSON.stringify(e) },
})
@ -119,7 +126,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
setIndexPatternTitles(await kibanaContext.indexPatterns.getTitles());
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobDetailsForm.errorGettingIndexPatternTitles', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.errorGettingIndexPatternTitles', {
defaultMessage: 'An error occurred getting the existing index pattern titles: {error}',
values: { error: JSON.stringify(e) },
})
@ -128,9 +135,9 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
})();
}, []);
const jobIdExists = jobIds.some(id => jobId === id);
const jobIdEmpty = jobId === '';
const jobIdValid = isJobIdValid(jobId);
const transformIdExists = transformIds.some(id => transformId === id);
const transformIdEmpty = transformId === '';
const transformIdValid = isTransformIdValid(transformId);
const indexNameExists = indexNames.some(name => destinationIndex === name);
const indexNameEmpty = destinationIndex === '';
@ -138,9 +145,9 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
const indexPatternTitleExists = indexPatternTitles.some(name => destinationIndex === name);
const valid =
!jobIdEmpty &&
jobIdValid &&
!jobIdExists &&
!transformIdEmpty &&
transformIdValid &&
!transformIdExists &&
!indexNameEmpty &&
indexNameValid &&
(!indexPatternTitleExists || !createIndexPattern) &&
@ -153,8 +160,8 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
continuousModeDelay,
createIndexPattern,
isContinuousModeEnabled,
jobId,
jobDescription,
transformId,
transformDescription,
destinationIndex,
touched: true,
valid,
@ -164,8 +171,8 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
continuousModeDelay,
createIndexPattern,
isContinuousModeEnabled,
jobId,
jobDescription,
transformId,
transformDescription,
destinationIndex,
valid,
]);
@ -173,22 +180,22 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
return (
<EuiForm>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobIdLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsForm.transformIdLabel', {
defaultMessage: 'Transform id',
})}
isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists}
isInvalid={(!transformIdEmpty && !transformIdValid) || transformIdExists}
error={[
...(!jobIdEmpty && !jobIdValid
...(!transformIdEmpty && !transformIdValid
? [
i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobIdInvalidError', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.transformIdInvalidError', {
defaultMessage:
'Must contain lowercase alphanumeric characters (a-z and 0-9), hyphens, and underscores only and must start and end with alphanumeric characters.',
}),
]
: []),
...(jobIdExists
...(transformIdExists
? [
i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobIdExistsError', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.transformIdExistsError', {
defaultMessage: 'A transform with this id already exists.',
}),
]
@ -197,28 +204,34 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
>
<EuiFieldText
placeholder="transform id"
value={jobId}
onChange={e => setJobId(e.target.value)}
aria-label={i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobIdInputAriaLabel', {
defaultMessage: 'Choose a unique transform id.',
})}
isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists}
value={transformId}
onChange={e => setTransformId(e.target.value)}
aria-label={i18n.translate(
'xpack.ml.dataframe.stepDetailsForm.transformIdInputAriaLabel',
{
defaultMessage: 'Choose a unique transform id.',
}
)}
isInvalid={(!transformIdEmpty && !transformIdValid) || transformIdExists}
/>
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobDescriptionLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsForm.transformDescriptionLabel', {
defaultMessage: 'Transform description',
})}
helpText={i18n.translate('xpack.ml.dataframe.jobDetailsForm.jobDescriptionHelpText', {
defaultMessage: 'Optional descriptive text.',
})}
helpText={i18n.translate(
'xpack.ml.dataframe.stepDetailsForm.transformDescriptionHelpText',
{
defaultMessage: 'Optional descriptive text.',
}
)}
>
<EuiFieldText
placeholder="transform description"
value={jobDescription}
onChange={e => setJobDescription(e.target.value)}
value={transformDescription}
onChange={e => setTransformDescription(e.target.value)}
aria-label={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.jobDescriptionInputAriaLabel',
'xpack.ml.dataframe.stepDetailsForm.transformDescriptionInputAriaLabel',
{
defaultMessage: 'Choose an optional transform description.',
}
@ -226,13 +239,13 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
/>
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsForm.destinationIndexLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsForm.destinationIndexLabel', {
defaultMessage: 'Destination index',
})}
isInvalid={!indexNameEmpty && !indexNameValid}
helpText={
indexNameExists &&
i18n.translate('xpack.ml.dataframe.jobDetailsForm.destinationIndexHelpText', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.destinationIndexHelpText', {
defaultMessage:
'An index with this name already exists. Be aware that running this transform will modify this destination index.',
})
@ -241,7 +254,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
!indexNameEmpty &&
!indexNameValid && [
<Fragment>
{i18n.translate('xpack.ml.dataframe.jobDetailsForm.destinationIndexInvalidError', {
{i18n.translate('xpack.ml.dataframe.stepDetailsForm.destinationIndexInvalidError', {
defaultMessage: 'Invalid destination index name.',
})}
<br />
@ -250,7 +263,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
target="_blank"
>
{i18n.translate(
'xpack.ml.dataframe.definePivotForm.destinationIndexInvalidErrorLink',
'xpack.ml.dataframe.stepDetailsForm.destinationIndexInvalidErrorLink',
{
defaultMessage: 'Learn more about index name limitations.',
}
@ -265,7 +278,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
value={destinationIndex}
onChange={e => setDestinationIndex(e.target.value)}
aria-label={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.destinationIndexInputAriaLabel',
'xpack.ml.dataframe.stepDetailsForm.destinationIndexInputAriaLabel',
{
defaultMessage: 'Choose a unique destination index name.',
}
@ -278,7 +291,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
error={
createIndexPattern &&
indexPatternTitleExists && [
i18n.translate('xpack.ml.dataframe.jobDetailsForm.indexPatternTitleError', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.indexPatternTitleError', {
defaultMessage: 'An index pattern with this title already exists.',
}),
]
@ -286,7 +299,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
>
<EuiSwitch
name="mlDataFrameCreateIndexPattern"
label={i18n.translate('xpack.ml.dataframe.jobCreateForm.createIndexPatternLabel', {
label={i18n.translate('xpack.ml.dataframe.stepCreateForm.createIndexPatternLabel', {
defaultMessage: 'Create index pattern',
})}
checked={createIndexPattern === true}
@ -296,7 +309,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
<EuiFormRow
helpText={
isContinuousModeAvailable === false
? i18n.translate('xpack.ml.dataframe.jobDetailsForm.continuousModeError', {
? i18n.translate('xpack.ml.dataframe.stepDetailsForm.continuousModeError', {
defaultMessage: 'Continuous mode is not available for indices without date fields.',
})
: ''
@ -304,7 +317,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
>
<EuiSwitch
name="mlDataFrameContinuousMode"
label={i18n.translate('xpack.ml.dataframe.jobCreateForm.continuousModeLabel', {
label={i18n.translate('xpack.ml.dataframe.stepCreateForm.continuousModeLabel', {
defaultMessage: 'Continuous mode',
})}
checked={isContinuousModeEnabled === true}
@ -316,13 +329,13 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
<Fragment>
<EuiFormRow
label={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.continuousModeDateFieldLabel',
'xpack.ml.dataframe.stepDetailsForm.continuousModeDateFieldLabel',
{
defaultMessage: 'Date field',
}
)}
helpText={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.continuousModeDateFieldHelpText',
'xpack.ml.dataframe.stepDetailsForm.continuousModeDateFieldHelpText',
{
defaultMessage: 'Select the date field that can be used to identify new documents.',
}
@ -335,19 +348,19 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
/>
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsForm.continuousModeDelayLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsForm.continuousModeDelayLabel', {
defaultMessage: 'Delay',
})}
isInvalid={!isContinuousModeDelayValid}
error={
!isContinuousModeDelayValid && [
i18n.translate('xpack.ml.dataframe.jobDetailsForm.continuousModeDelayError', {
i18n.translate('xpack.ml.dataframe.stepDetailsForm.continuousModeDelayError', {
defaultMessage: 'Invalid delay format',
}),
]
}
helpText={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.continuousModeDelayHelpText',
'xpack.ml.dataframe.stepDetailsForm.continuousModeDelayHelpText',
{
defaultMessage: 'Time delay between current time and latest input data time.',
}
@ -358,7 +371,7 @@ export const JobDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChange
value={continuousModeDelay}
onChange={e => setContinuousModeDelay(e.target.value)}
aria-label={i18n.translate(
'xpack.ml.dataframe.jobDetailsForm.continuousModeAriaLabel',
'xpack.ml.dataframe.stepDetailsForm.continuousModeAriaLabel',
{
defaultMessage: 'Choose a delay.',
}

View file

@ -10,15 +10,15 @@ import { i18n } from '@kbn/i18n';
import { EuiFieldText, EuiFormRow } from '@elastic/eui';
import { JobDetailsExposedState } from './job_details_form';
import { StepDetailsExposedState } from './step_details_form';
export const JobDetailsSummary: SFC<JobDetailsExposedState> = React.memo(
export const StepDetailsSummary: SFC<StepDetailsExposedState> = React.memo(
({
continuousModeDateField,
createIndexPattern,
isContinuousModeEnabled,
jobId,
jobDescription,
transformId,
transformDescription,
destinationIndex,
touched,
}) => {
@ -27,7 +27,7 @@ export const JobDetailsSummary: SFC<JobDetailsExposedState> = React.memo(
}
const destinationIndexHelpText = createIndexPattern
? i18n.translate('xpack.ml.dataframe.jobDetailsSummary.createIndexPatternMessage', {
? i18n.translate('xpack.ml.dataframe.stepDetailsSummary.createIndexPatternMessage', {
defaultMessage: 'A Kibana index pattern will be created for this transform.',
})
: '';
@ -35,22 +35,22 @@ export const JobDetailsSummary: SFC<JobDetailsExposedState> = React.memo(
return (
<Fragment>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsSummary.jobIdLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsSummary.transformIdLabel', {
defaultMessage: 'Transform id',
})}
>
<EuiFieldText defaultValue={jobId} disabled={true} />
<EuiFieldText defaultValue={transformId} disabled={true} />
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.jobDetailsSummary.jobDescriptionLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsSummary.transformDescriptionLabel', {
defaultMessage: 'Transform description',
})}
>
<EuiFieldText defaultValue={jobDescription} disabled={true} />
<EuiFieldText defaultValue={transformDescription} disabled={true} />
</EuiFormRow>
<EuiFormRow
helpText={destinationIndexHelpText}
label={i18n.translate('xpack.ml.dataframe.jobDetailsSummary.destinationIndexLabel', {
label={i18n.translate('xpack.ml.dataframe.stepDetailsSummary.destinationIndexLabel', {
defaultMessage: 'Destination index',
})}
>
@ -59,7 +59,7 @@ export const JobDetailsSummary: SFC<JobDetailsExposedState> = React.memo(
{isContinuousModeEnabled && (
<EuiFormRow
label={i18n.translate(
'xpack.ml.dataframe.jobDetailsSummary.continuousModeDateFieldLabel',
'xpack.ml.dataframe.stepDetailsSummary.continuousModeDateFieldLabel',
{
defaultMessage: 'Continuous mode date field',
}

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export * from './wizard_nav';
export { Wizard } from './wizard';

View file

@ -0,0 +1,174 @@
/*
* 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 React, { Fragment, SFC, useContext, useRef, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiSteps, EuiStepStatus } from '@elastic/eui';
import { isKibanaContext, getCreateRequestBody, KibanaContext } from '../../../../common';
import {
StepDefineExposedState,
StepDefineForm,
StepDefineSummary,
getDefaultStepDefineState,
} from '../step_define';
import { getDefaultStepCreateState, StepCreateForm, StepCreateSummary } from '../step_create';
import { getDefaultStepDetailsState, StepDetailsForm, StepDetailsSummary } from '../step_details';
import { WizardNav } from '../wizard_nav';
enum WIZARD_STEPS {
DEFINE,
DETAILS,
CREATE,
}
interface DefinePivotStepProps {
isCurrentStep: boolean;
stepDefineState: StepDefineExposedState;
setCurrentStep: React.Dispatch<React.SetStateAction<WIZARD_STEPS>>;
setStepDefineState: React.Dispatch<React.SetStateAction<StepDefineExposedState>>;
}
const StepDefine: SFC<DefinePivotStepProps> = ({
isCurrentStep,
stepDefineState,
setCurrentStep,
setStepDefineState,
}) => {
const definePivotRef = useRef(null);
return (
<Fragment>
<div ref={definePivotRef} />
{isCurrentStep && (
<Fragment>
<StepDefineForm onChange={setStepDefineState} overrides={{ ...stepDefineState }} />
<WizardNav
next={() => setCurrentStep(WIZARD_STEPS.DETAILS)}
nextActive={stepDefineState.valid}
/>
</Fragment>
)}
{!isCurrentStep && <StepDefineSummary {...stepDefineState} />}
</Fragment>
);
};
export const Wizard: SFC = React.memo(() => {
const kibanaContext = useContext(KibanaContext);
if (!isKibanaContext(kibanaContext)) {
return null;
}
const indexPattern = kibanaContext.currentIndexPattern;
// The current WIZARD_STEP
const [currentStep, setCurrentStep] = useState(WIZARD_STEPS.DEFINE);
// The DEFINE state
const [stepDefineState, setStepDefineState] = useState(getDefaultStepDefineState(kibanaContext));
// The DETAILS state
const [stepDetailsState, setStepDetailsState] = useState(getDefaultStepDetailsState());
const stepDetails =
currentStep === WIZARD_STEPS.DETAILS ? (
<StepDetailsForm onChange={setStepDetailsState} overrides={stepDetailsState} />
) : (
<StepDetailsSummary {...stepDetailsState} />
);
const transformConfig = getCreateRequestBody(
indexPattern.title,
stepDefineState,
stepDetailsState
);
// The CREATE state
const [stepCreateState, setStepCreateState] = useState(getDefaultStepCreateState);
const stepCreate =
currentStep === WIZARD_STEPS.CREATE ? (
<StepCreateForm
createIndexPattern={stepDetailsState.createIndexPattern}
transformId={stepDetailsState.transformId}
transformConfig={transformConfig}
onChange={setStepCreateState}
overrides={stepCreateState}
/>
) : (
<StepCreateSummary />
);
// scroll to the currently selected wizard step
/*
function scrollToRef() {
if (definePivotRef !== null && definePivotRef.current !== null) {
// TODO Fix types
const dummy = definePivotRef as any;
const headerOffset = 70;
window.scrollTo(0, dummy.current.offsetTop - headerOffset);
}
}
*/
const stepsConfig = [
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.stepDefineTitle', {
defaultMessage: 'Define pivot',
}),
children: (
<StepDefine
isCurrentStep={currentStep === WIZARD_STEPS.DEFINE}
stepDefineState={stepDefineState}
setCurrentStep={setCurrentStep}
setStepDefineState={setStepDefineState}
/>
),
},
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.stepDetailsTitle', {
defaultMessage: 'Transform details',
}),
children: (
<Fragment>
{stepDetails}
{currentStep === WIZARD_STEPS.DETAILS && (
<WizardNav
previous={() => {
setCurrentStep(WIZARD_STEPS.DEFINE);
// scrollToRef();
}}
next={() => setCurrentStep(WIZARD_STEPS.CREATE)}
nextActive={stepDetailsState.valid}
/>
)}
</Fragment>
),
status: currentStep >= WIZARD_STEPS.DETAILS ? undefined : ('incomplete' as EuiStepStatus),
},
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.stepCreateTitle', {
defaultMessage: 'Create',
}),
children: (
<Fragment>
{stepCreate}
{currentStep === WIZARD_STEPS.CREATE && !stepCreateState.created && (
<WizardNav previous={() => setCurrentStep(WIZARD_STEPS.DETAILS)} />
)}
</Fragment>
),
status: currentStep >= WIZARD_STEPS.CREATE ? undefined : ('incomplete' as EuiStepStatus),
},
];
return <EuiSteps steps={stepsConfig} />;
});

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { CreateJobButton } from './create_job_button';
export { WizardNav } from './wizard_nav';

View file

@ -20,7 +20,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import { Wizard } from './wizard';
import { Wizard } from './components/wizard';
export const Page: SFC = () => (
<EuiPage>

View file

@ -8,22 +8,43 @@ import uiRoutes from 'ui/routes';
// @ts-ignore
import { checkBasicLicense } from '../../../license/check_license';
// @ts-ignore
import { checkCreateDataFrameJobsPrivilege } from '../../../privilege/check_privilege';
import { checkCreateDataFrameTransformPrivilege } from '../../../privilege/check_privilege';
// @ts-ignore
import { loadCurrentIndexPattern, loadCurrentSavedSearch } from '../../../util/index_utils';
// @ts-ignore
import { getDataFrameCreateBreadcrumbs } from '../../breadcrumbs';
import { loadIndexPatterns } from '../../../util/index_utils';
const template = `<ml-nav-menu name="new_data_frame" /><ml-new-data-frame />`;
import indexOrSearchTemplate from '../../../jobs/new_job/wizard/steps/index_or_search/index_or_search.html';
uiRoutes.when('/data_frames/new_job/step/pivot?', {
template,
import {
getDataFrameCreateBreadcrumbs,
getDataFrameIndexOrSearchBreadcrumbs,
} from '../../breadcrumbs';
const wizardTemplate = `<ml-nav-menu name="new_data_frame" /><ml-new-data-frame />`;
uiRoutes.when('/data_frames/new_transform/step/pivot?', {
template: wizardTemplate,
k7Breadcrumbs: getDataFrameCreateBreadcrumbs,
resolve: {
CheckLicense: checkBasicLicense,
privileges: checkCreateDataFrameJobsPrivilege,
privileges: checkCreateDataFrameTransformPrivilege,
indexPattern: loadCurrentIndexPattern,
savedSearch: loadCurrentSavedSearch,
},
});
uiRoutes.when('/data_frames/new_transform', {
redirectTo: '/data_frames/new_transform/step/index_or_search',
});
uiRoutes.when('/data_frames/new_transform/step/index_or_search', {
template: indexOrSearchTemplate,
k7Breadcrumbs: getDataFrameIndexOrSearchBreadcrumbs,
resolve: {
CheckLicense: checkBasicLicense,
privileges: checkCreateDataFrameTransformPrivilege,
indexPatterns: loadIndexPatterns,
nextStepPath: () => '#data_frames/new_transform/step/pivot',
},
});

View file

@ -1,182 +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.
*/
import React, { Fragment, SFC, useContext, useRef, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiSteps, EuiStepStatus } from '@elastic/eui';
import { WizardNav } from '../../components/wizard_nav';
import {
DefinePivotExposedState,
DefinePivotForm,
DefinePivotSummary,
getDefaultPivotState,
} from '../../components/define_pivot';
import {
getDefaultJobCreateState,
JobCreateForm,
JobCreateSummary,
} from '../../components/job_create';
import { getDataFrameRequest } from '../../common';
import {
getDefaultJobDetailsState,
JobDetailsForm,
JobDetailsSummary,
} from '../../components/job_details';
import { isKibanaContext, KibanaContext } from '../../common';
enum WIZARD_STEPS {
DEFINE_PIVOT,
JOB_DETAILS,
JOB_CREATE,
}
interface DefinePivotStepProps {
isCurrentStep: boolean;
pivotState: DefinePivotExposedState;
setCurrentStep: React.Dispatch<React.SetStateAction<WIZARD_STEPS>>;
setPivot: React.Dispatch<React.SetStateAction<DefinePivotExposedState>>;
}
const DefinePivotStep: SFC<DefinePivotStepProps> = ({
isCurrentStep,
pivotState,
setCurrentStep,
setPivot,
}) => {
const definePivotRef = useRef(null);
return (
<Fragment>
<div ref={definePivotRef} />
{isCurrentStep && (
<Fragment>
<DefinePivotForm onChange={setPivot} overrides={{ ...pivotState }} />
<WizardNav
next={() => setCurrentStep(WIZARD_STEPS.JOB_DETAILS)}
nextActive={pivotState.valid}
/>
</Fragment>
)}
{!isCurrentStep && <DefinePivotSummary {...pivotState} />}
</Fragment>
);
};
export const Wizard: SFC = React.memo(() => {
const kibanaContext = useContext(KibanaContext);
if (!isKibanaContext(kibanaContext)) {
return null;
}
const indexPattern = kibanaContext.currentIndexPattern;
// The current WIZARD_STEP
const [currentStep, setCurrentStep] = useState(WIZARD_STEPS.DEFINE_PIVOT);
// The DEFINE_PIVOT state
const [pivotState, setPivot] = useState(getDefaultPivotState(kibanaContext));
// The JOB_DETAILS state
const [jobDetailsState, setJobDetails] = useState(getDefaultJobDetailsState());
const jobDetails =
currentStep === WIZARD_STEPS.JOB_DETAILS ? (
<JobDetailsForm onChange={setJobDetails} overrides={jobDetailsState} />
) : (
<JobDetailsSummary {...jobDetailsState} />
);
const jobConfig = getDataFrameRequest(indexPattern.title, pivotState, jobDetailsState);
// The JOB_CREATE state
const [jobCreateState, setJobCreate] = useState(getDefaultJobCreateState);
const jobCreate =
currentStep === WIZARD_STEPS.JOB_CREATE ? (
<JobCreateForm
createIndexPattern={jobDetailsState.createIndexPattern}
jobId={jobDetailsState.jobId}
jobConfig={jobConfig}
onChange={setJobCreate}
overrides={jobCreateState}
/>
) : (
<JobCreateSummary />
);
// scroll to the currently selected wizard step
/*
function scrollToRef() {
if (definePivotRef !== null && definePivotRef.current !== null) {
// TODO Fix types
const dummy = definePivotRef as any;
const headerOffset = 70;
window.scrollTo(0, dummy.current.offsetTop - headerOffset);
}
}
*/
const stepsConfig = [
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.definePivotStepTitle', {
defaultMessage: 'Define pivot',
}),
children: (
<DefinePivotStep
isCurrentStep={currentStep === WIZARD_STEPS.DEFINE_PIVOT}
pivotState={pivotState}
setCurrentStep={setCurrentStep}
setPivot={setPivot}
/>
),
},
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.jobDetailsStepTitle', {
defaultMessage: 'Transform details',
}),
children: (
<Fragment>
{jobDetails}
{currentStep === WIZARD_STEPS.JOB_DETAILS && (
<WizardNav
previous={() => {
setCurrentStep(WIZARD_STEPS.DEFINE_PIVOT);
// scrollToRef();
}}
next={() => setCurrentStep(WIZARD_STEPS.JOB_CREATE)}
nextActive={jobDetailsState.valid}
/>
)}
</Fragment>
),
status: currentStep >= WIZARD_STEPS.JOB_DETAILS ? undefined : ('incomplete' as EuiStepStatus),
},
{
title: i18n.translate('xpack.ml.dataframe.transformsWizard.createStepTitle', {
defaultMessage: 'Create',
}),
children: (
<Fragment>
{jobCreate}
{currentStep === WIZARD_STEPS.JOB_CREATE && !jobCreateState.created && (
<WizardNav previous={() => setCurrentStep(WIZARD_STEPS.JOB_DETAILS)} />
)}
</Fragment>
),
status: currentStep >= WIZARD_STEPS.JOB_CREATE ? undefined : ('incomplete' as EuiStepStatus),
},
];
return <EuiSteps steps={stepsConfig} />;
});

View file

@ -1,7 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Data Frame: Job List <DataFrameJobList /> Minimal initialization 1`] = `
<ProgressBar
isLoading={false}
/>
`;

View file

@ -1,25 +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.
*/
import mockDataFrameJobListRow from './__mocks__/data_frame_job_list_row.json';
import { DATA_FRAME_TASK_STATE, isCompletedBatchJob } from './common';
describe('Data Frame: isCompletedBatchJob()', () => {
test('isCompletedBatchJob()', () => {
// check the job config/state against the conditions
// that will be used by isCompletedBatchJob()
// followed by a call to isCompletedBatchJob() itself
expect(mockDataFrameJobListRow.state.checkpoint === 1).toBe(true);
expect(mockDataFrameJobListRow.sync === undefined).toBe(true);
expect(mockDataFrameJobListRow.state.task_state === DATA_FRAME_TASK_STATE.STOPPED).toBe(true);
expect(isCompletedBatchJob(mockDataFrameJobListRow)).toBe(true);
// adapt the mock config to resemble a non-completed job.
mockDataFrameJobListRow.state.checkpoint = 0;
expect(isCompletedBatchJob(mockDataFrameJobListRow)).toBe(false);
});
});

View file

@ -1,40 +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.
*/
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
import { ml } from '../../../../../../services/ml_api_service';
import { refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../../../../../common';
import { DATA_FRAME_TASK_STATE, DataFrameJobListRow } from '../common';
export const deleteJob = async (d: DataFrameJobListRow) => {
try {
if (d.state.task_state === DATA_FRAME_TASK_STATE.FAILED) {
await ml.dataFrame.stopDataFrameTransformsJob(
d.config.id,
d.state.task_state === DATA_FRAME_TASK_STATE.FAILED,
true
);
}
await ml.dataFrame.deleteDataFrameTransformsJob(d.config.id);
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobsList.deleteJobSuccessMessage', {
defaultMessage: 'Data frame transform {jobId} deleted successfully.',
values: { jobId: d.config.id },
})
);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobsList.deleteJobErrorMessage', {
defaultMessage: 'An error occurred deleting the data frame transform {jobId}: {error}',
values: { jobId: d.config.id, error: JSON.stringify(e) },
})
);
}
refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH);
};

View file

@ -1,10 +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.
*/
export { getJobsFactory } from './get_jobs';
export { deleteJob } from './delete_job';
export { startJob } from './start_job';
export { stopJob } from './stop_job';

View file

@ -1,36 +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.
*/
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
import { ml } from '../../../../../../services/ml_api_service';
import { refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../../../../../common';
import { DATA_FRAME_TASK_STATE, DataFrameJobListRow } from '../common';
export const startJob = async (d: DataFrameJobListRow) => {
try {
await ml.dataFrame.startDataFrameTransformsJob(
d.config.id,
d.state.task_state === DATA_FRAME_TASK_STATE.FAILED
);
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobsList.startJobSuccessMessage', {
defaultMessage: 'Data frame transform {jobId} started successfully.',
values: { jobId: d.config.id },
})
);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobsList.startJobErrorMessage', {
defaultMessage: 'An error occurred starting the data frame transform {jobId}: {error}',
values: { jobId: d.config.id, error: JSON.stringify(e) },
})
);
}
refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH);
};

View file

@ -1,37 +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.
*/
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
import { ml } from '../../../../../../services/ml_api_service';
import { refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../../../../../common';
import { DATA_FRAME_TASK_STATE, DataFrameJobListRow } from '../common';
export const stopJob = async (d: DataFrameJobListRow) => {
try {
await ml.dataFrame.stopDataFrameTransformsJob(
d.config.id,
d.state.task_state === DATA_FRAME_TASK_STATE.FAILED,
true
);
toastNotifications.addSuccess(
i18n.translate('xpack.ml.dataframe.jobsList.stopJobSuccessMessage', {
defaultMessage: 'Data frame transform {jobId} stopped successfully.',
values: { jobId: d.config.id },
})
);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.ml.dataframe.jobsList.stopJobErrorMessage', {
defaultMessage: 'An error occurred stopping the data frame transform {jobId}: {error}',
values: { jobId: d.config.id, error: JSON.stringify(e) },
})
);
}
refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH);
};

View file

@ -16,7 +16,7 @@ exports[`Data Frame: Job List <Page /> Minimal initialization 1`] = `
<h1>
<FormattedMessage
defaultMessage="Data frame transforms"
id="xpack.ml.dataframe.jobsList.dataFrameTitle"
id="xpack.ml.dataframe.transformList.dataFrameTitle"
values={Object {}}
/>
<span>
@ -40,7 +40,7 @@ exports[`Data Frame: Job List <Page /> Minimal initialization 1`] = `
/>
</EuiFlexItem>
<EuiFlexItem>
<CreateJobButton />
<CreateTransformButton />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentHeaderSection>
@ -54,7 +54,7 @@ exports[`Data Frame: Job List <Page /> Minimal initialization 1`] = `
hasShadow={false}
paddingSize="m"
>
<DataFrameJobList />
<DataFrameTransformList />
</EuiPanel>
</EuiPageContentBody>
</EuiPageBody>

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Data Frame: Job List <CreateJobButton /> Minimal initialization 1`] = `
exports[`Data Frame: Transform List <CreateTransformButton /> Minimal initialization 1`] = `
<EuiToolTip
content="Your license has expired. Please contact your administrator."
delay="regular"
@ -19,7 +19,7 @@ exports[`Data Frame: Job List <CreateJobButton /> Minimal initialization 1`] = `
>
<FormattedMessage
defaultMessage="Create transform"
id="xpack.ml.dataframe.jobsList.createDataFrameButton"
id="xpack.ml.dataframe.transformList.createDataFrameButton"
values={Object {}}
/>
</EuiButton>

View file

@ -7,12 +7,11 @@
import { shallow } from 'enzyme';
import React from 'react';
import './job_list.test.mocks';
import { DataFrameJobList } from './job_list';
import { CreateTransformButton } from './create_transform_button';
describe('Data Frame: Job List <DataFrameJobList />', () => {
describe('Data Frame: Transform List <CreateTransformButton />', () => {
test('Minimal initialization', () => {
const wrapper = shallow(<DataFrameJobList />);
const wrapper = shallow(<CreateTransformButton />);
expect(wrapper).toMatchSnapshot();
});

View file

@ -17,11 +17,11 @@ import {
import { moveToDataFrameWizard } from '../../../../common';
export const CreateJobButton: SFC = () => {
export const CreateTransformButton: SFC = () => {
const disabled =
!checkPermission('canCreateDataFrameJob') ||
!checkPermission('canPreviewDataFrameJob') ||
!checkPermission('canStartStopDataFrameJob');
!checkPermission('canCreateDataFrame') ||
!checkPermission('canPreviewDataFrame') ||
!checkPermission('canStartStopDataFrame');
const button = (
<EuiButton
@ -33,7 +33,7 @@ export const CreateJobButton: SFC = () => {
data-test-subj="mlDataFramesButtonCreate"
>
<FormattedMessage
id="xpack.ml.dataframe.jobsList.createDataFrameButton"
id="xpack.ml.dataframe.transformList.createDataFrameButton"
defaultMessage="Create transform"
/>
</EuiButton>
@ -41,7 +41,7 @@ export const CreateJobButton: SFC = () => {
if (disabled) {
return (
<EuiToolTip position="top" content={createPermissionFailureMessage('canCreateDataFrameJob')}>
<EuiToolTip position="top" content={createPermissionFailureMessage('canCreateDataFrame')}>
{button}
</EuiToolTip>
);

View file

@ -4,5 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export * from './list_form';
export * from './list_summary';
export { CreateTransformButton } from './create_transform_button';

Some files were not shown because too many files have changed in this diff Show more