mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[ML] Rename index pattern references to data view (Part 2) (#171820)
- Renames references to index patterns to data views in function and variable names. - Some inconsistent naming of schemas for data frame analytics was cleaned up as part of this PR. - Note this doesn't cover the whole ml owned codebase but just code related to data frame analytics.
This commit is contained in:
parent
5d3c1bc2bb
commit
aae3e5d087
47 changed files with 309 additions and 338 deletions
|
@ -10,7 +10,7 @@ export {
|
|||
getDataGridSchemaFromESFieldType,
|
||||
getDataGridSchemaFromKibanaFieldType,
|
||||
getFeatureImportance,
|
||||
getFieldsFromKibanaIndexPattern,
|
||||
getFieldsFromKibanaDataView,
|
||||
getNestedOrEscapedVal,
|
||||
getProcessedFields,
|
||||
getTopClasses,
|
||||
|
|
|
@ -83,7 +83,7 @@ export const euiDataGridToolbarSettings = {
|
|||
* @param {DataView} dataView - The Kibana data view.
|
||||
* @returns {string[]} - The array of field names from the data view.
|
||||
*/
|
||||
export const getFieldsFromKibanaIndexPattern = (dataView: DataView): string[] => {
|
||||
export const getFieldsFromKibanaDataView = (dataView: DataView): string[] => {
|
||||
const allFields = dataView.fields.map((f) => f.name);
|
||||
const dataViewFields: string[] = allFields.filter((f) => {
|
||||
if (dataView.metaFields.includes(f)) {
|
||||
|
|
|
@ -158,9 +158,9 @@ export interface UseIndexDataReturnType
|
|||
*/
|
||||
renderCellValue: RenderCellValue;
|
||||
/**
|
||||
* Optional index pattern fields.
|
||||
* Optional data view fields.
|
||||
*/
|
||||
indexPatternFields?: string[];
|
||||
dataViewFields?: string[];
|
||||
/**
|
||||
* Optional time range.
|
||||
*/
|
||||
|
|
|
@ -101,7 +101,7 @@ export interface ScatterplotMatrixProps {
|
|||
legendType?: LegendType;
|
||||
searchQuery?: estypes.QueryDslQueryContainer;
|
||||
runtimeMappings?: RuntimeMappings;
|
||||
indexPattern?: DataView;
|
||||
dataView?: DataView;
|
||||
query?: Query;
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
|
|||
legendType,
|
||||
searchQuery,
|
||||
runtimeMappings,
|
||||
indexPattern,
|
||||
dataView,
|
||||
query,
|
||||
}) => {
|
||||
const { esSearch } = useMlApiContext();
|
||||
|
@ -210,9 +210,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
|
|||
vegaSpec.data = {
|
||||
url: {
|
||||
'%context%': true,
|
||||
...(indexPattern?.timeFieldName
|
||||
? { ['%timefield%']: `${indexPattern?.timeFieldName}` }
|
||||
: {}),
|
||||
...(dataView?.timeFieldName ? { ['%timefield%']: `${dataView?.timeFieldName}` } : {}),
|
||||
index,
|
||||
body: {
|
||||
fields: fieldsToFetch,
|
||||
|
@ -300,7 +298,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
|
|||
}
|
||||
|
||||
const combinedRuntimeMappings =
|
||||
indexPattern && getCombinedRuntimeMappings(indexPattern, runtimeMappings);
|
||||
dataView && getCombinedRuntimeMappings(dataView, runtimeMappings);
|
||||
|
||||
const body = {
|
||||
fields: queryFields,
|
||||
|
|
|
@ -37,12 +37,10 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
} = useMlKibana();
|
||||
const trainedModelsApiService = useTrainedModelsApiService();
|
||||
|
||||
const [indexPattern, setIndexPattern] = useState<DataView | undefined>(undefined);
|
||||
const [indexPatternErrorMessage, setIndexPatternErrorMessage] = useState<undefined | string>(
|
||||
undefined
|
||||
);
|
||||
const [dataView, setDataView] = useState<DataView | undefined>(undefined);
|
||||
const [dataViewErrorMessage, setDataViewErrorMessage] = useState<undefined | string>(undefined);
|
||||
const [isInitialized, setIsInitialized] = useState<boolean>(false);
|
||||
const [needsDestIndexPattern, setNeedsDestIndexPattern] = useState<boolean>(false);
|
||||
const [needsDestDataView, setNeedsDestDataView] = useState<boolean>(false);
|
||||
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState<boolean>(false);
|
||||
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsConfig | undefined>(undefined);
|
||||
const [jobCapsServiceErrorMessage, setJobCapsServiceErrorMessage] = useState<undefined | string>(
|
||||
|
@ -100,39 +98,39 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
try {
|
||||
const destIndex = getDestinationIndex(jobConfigUpdate);
|
||||
const destDataViewId = (await getDataViewIdFromName(destIndex)) ?? destIndex;
|
||||
let dataView: DataView | undefined;
|
||||
let fetchedDataView: DataView | undefined;
|
||||
|
||||
try {
|
||||
dataView = await dataViews.get(destDataViewId);
|
||||
fetchedDataView = await dataViews.get(destDataViewId);
|
||||
|
||||
// Force refreshing the fields list here because a user directly coming
|
||||
// from the job creation wizard might land on the page without the
|
||||
// data view being fully initialized because it was created
|
||||
// before the analytics job populated the destination index.
|
||||
await dataViews.refreshFields(dataView);
|
||||
await dataViews.refreshFields(fetchedDataView);
|
||||
} catch (e) {
|
||||
dataView = undefined;
|
||||
fetchedDataView = undefined;
|
||||
}
|
||||
|
||||
if (dataView === undefined) {
|
||||
setNeedsDestIndexPattern(true);
|
||||
if (fetchedDataView === undefined) {
|
||||
setNeedsDestDataView(true);
|
||||
const sourceIndex = jobConfigUpdate.source.index[0];
|
||||
const sourceDataViewId = (await getDataViewIdFromName(sourceIndex)) ?? sourceIndex;
|
||||
try {
|
||||
dataView = await dataViews.get(sourceDataViewId);
|
||||
fetchedDataView = await dataViews.get(sourceDataViewId);
|
||||
} catch (e) {
|
||||
dataView = undefined;
|
||||
fetchedDataView = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataView !== undefined) {
|
||||
await newJobCapsServiceAnalytics.initializeFromDataVIew(dataView);
|
||||
if (fetchedDataView !== undefined) {
|
||||
await newJobCapsServiceAnalytics.initializeFromDataVIew(fetchedDataView);
|
||||
setJobConfig(analyticsConfigs.data_frame_analytics[0]);
|
||||
setIndexPattern(dataView);
|
||||
setDataView(fetchedDataView);
|
||||
setIsInitialized(true);
|
||||
setIsLoadingJobConfig(false);
|
||||
} else {
|
||||
setIndexPatternErrorMessage(
|
||||
setDataViewErrorMessage(
|
||||
i18n.translate('xpack.ml.dataframe.analytics.results.dataViewMissingErrorMessage', {
|
||||
defaultMessage:
|
||||
'To view this page, a Kibana data view is necessary for either the destination or source index of this analytics job.',
|
||||
|
@ -153,15 +151,15 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
}, []);
|
||||
|
||||
return {
|
||||
indexPattern,
|
||||
indexPatternErrorMessage,
|
||||
dataView,
|
||||
dataViewErrorMessage,
|
||||
isInitialized,
|
||||
isLoadingJobConfig,
|
||||
jobCapsServiceErrorMessage,
|
||||
jobConfig,
|
||||
jobConfigErrorMessage,
|
||||
jobStatus,
|
||||
needsDestIndexPattern,
|
||||
needsDestDataView,
|
||||
totalFeatureImportance,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -356,9 +356,9 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const indexPatternFieldsTableItems = useMemo(() => {
|
||||
if (indexData?.indexPatternFields !== undefined) {
|
||||
return indexData.indexPatternFields.map((field) => ({
|
||||
const dataViewFieldsTableItems = useMemo(() => {
|
||||
if (indexData?.dataViewFields !== undefined) {
|
||||
return indexData.dataViewFields.map((field) => ({
|
||||
name: field,
|
||||
is_included: false,
|
||||
is_required: false,
|
||||
|
@ -366,7 +366,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
}
|
||||
return [];
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [`${indexData?.indexPatternFields}`]);
|
||||
}, [`${indexData?.dataViewFields}`]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof savedSearchQueryStr === 'string') {
|
||||
|
@ -377,11 +377,11 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
|
||||
useEffect(() => {
|
||||
if (isJobTypeWithDepVar) {
|
||||
const indexPatternRuntimeFields = getCombinedRuntimeMappings(selectedDataView);
|
||||
const dataViewRuntimeFields = getCombinedRuntimeMappings(selectedDataView);
|
||||
let runtimeOptions;
|
||||
|
||||
if (indexPatternRuntimeFields) {
|
||||
runtimeOptions = getRuntimeDepVarOptions(jobType, indexPatternRuntimeFields);
|
||||
if (dataViewRuntimeFields) {
|
||||
runtimeOptions = getRuntimeDepVarOptions(jobType, dataViewRuntimeFields);
|
||||
}
|
||||
|
||||
loadDepVarOptions(form, runtimeOptions);
|
||||
|
@ -527,7 +527,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
legendType: getScatterplotMatrixLegendType(jobType),
|
||||
searchQuery: jobConfigQuery,
|
||||
runtimeMappings,
|
||||
indexPattern: selectedDataView,
|
||||
dataView: selectedDataView,
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
|
@ -571,7 +571,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
const tableItems =
|
||||
includesTableItems.length > 0 && !noDocsContainMappedFields
|
||||
? includesTableItems
|
||||
: indexPatternFieldsTableItems;
|
||||
: dataViewFieldsTableItems;
|
||||
|
||||
return (
|
||||
<FieldStatsFlyoutProvider
|
||||
|
@ -592,7 +592,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
|
|||
fullWidth
|
||||
>
|
||||
<ExplorationQueryBar
|
||||
indexPattern={selectedDataView}
|
||||
dataView={selectedDataView}
|
||||
setSearchQuery={setJobConfigQuery}
|
||||
query={query}
|
||||
/>
|
||||
|
|
|
@ -42,13 +42,8 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
|
||||
const { createAnalyticsJob, setFormState, startAnalyticsJob } = actions;
|
||||
const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state;
|
||||
const {
|
||||
createIndexPattern,
|
||||
destinationIndex,
|
||||
destinationIndexPatternTitleExists,
|
||||
jobId,
|
||||
jobType,
|
||||
} = state.form;
|
||||
const { createDataView, destinationIndex, destinationDataViewTitleExists, jobId, jobType } =
|
||||
state.form;
|
||||
|
||||
const [startChecked, setStartChecked] = useState<boolean>(true);
|
||||
const [creationTriggered, setCreationTriggered] = useState<boolean>(false);
|
||||
|
@ -56,7 +51,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (canCreateDataView === false) {
|
||||
setFormState({ createIndexPattern: false });
|
||||
setFormState({ createDataView: false });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [capabilities]);
|
||||
|
@ -106,7 +101,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
onChange={(e) => {
|
||||
setStartChecked(e.target.checked);
|
||||
if (e.target.checked === false) {
|
||||
setFormState({ createIndexPattern: false });
|
||||
setFormState({ createDataView: false });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -117,8 +112,8 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
<EuiFormRow
|
||||
fullWidth
|
||||
isInvalid={
|
||||
(createIndexPattern && destinationIndexPatternTitleExists) ||
|
||||
createIndexPattern === false ||
|
||||
(createDataView && destinationDataViewTitleExists) ||
|
||||
createDataView === false ||
|
||||
canCreateDataView === false
|
||||
}
|
||||
error={[
|
||||
|
@ -134,7 +129,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
</EuiText>,
|
||||
]
|
||||
: []),
|
||||
...(createIndexPattern && destinationIndexPatternTitleExists
|
||||
...(createDataView && destinationDataViewTitleExists
|
||||
? [
|
||||
i18n.translate(
|
||||
'xpack.ml.dataframe.analytics.create.dataViewExistsError',
|
||||
|
@ -146,7 +141,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
),
|
||||
]
|
||||
: []),
|
||||
...(!createIndexPattern && !destinationIndexPatternTitleExists
|
||||
...(!createDataView && !destinationDataViewTitleExists
|
||||
? [
|
||||
<EuiText size="xs" color="warning">
|
||||
{i18n.translate(
|
||||
|
@ -171,8 +166,8 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
defaultMessage: 'Create data view',
|
||||
}
|
||||
)}
|
||||
checked={createIndexPattern === true}
|
||||
onChange={() => setFormState({ createIndexPattern: !createIndexPattern })}
|
||||
checked={createDataView === true}
|
||||
onChange={() => setFormState({ createDataView: !createDataView })}
|
||||
data-test-subj="mlAnalyticsCreateJobWizardCreateDataViewCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
@ -186,7 +181,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
|
|||
disabled={
|
||||
!isValid ||
|
||||
!isAdvancedEditorValidJson ||
|
||||
(destinationIndexPatternTitleExists === true && createIndexPattern === true)
|
||||
(destinationDataViewTitleExists === true && createDataView === true)
|
||||
}
|
||||
onClick={handleCreation}
|
||||
fill
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
getFieldType,
|
||||
getDataGridSchemaFromKibanaFieldType,
|
||||
getDataGridSchemaFromESFieldType,
|
||||
getFieldsFromKibanaIndexPattern,
|
||||
getFieldsFromKibanaDataView,
|
||||
showDataGridColumnChartErrorMessageToast,
|
||||
useDataGrid,
|
||||
useRenderCellValue,
|
||||
|
@ -58,8 +58,8 @@ function getRuntimeFieldColumns(runtimeMappings: RuntimeMappings) {
|
|||
});
|
||||
}
|
||||
|
||||
function getIndexPatternColumns(indexPattern: DataView, fieldsFilter: string[]) {
|
||||
const { fields } = indexPattern;
|
||||
function getDataViewColumns(dataView: DataView, fieldsFilter: string[]) {
|
||||
const { fields } = dataView;
|
||||
|
||||
return fields
|
||||
.filter((field) => fieldsFilter.includes(field.name))
|
||||
|
@ -78,7 +78,7 @@ function getIndexPatternColumns(indexPattern: DataView, fieldsFilter: string[])
|
|||
}
|
||||
|
||||
export const useIndexData = (
|
||||
indexPattern: DataView,
|
||||
dataView: DataView,
|
||||
query: Record<string, any> | undefined,
|
||||
toastNotifications: CoreSetup['notifications']['toasts'],
|
||||
runtimeMappings?: RuntimeMappings
|
||||
|
@ -87,7 +87,7 @@ export const useIndexData = (
|
|||
// This is a workaround to avoid passing potentially thousands of unpopulated fields
|
||||
// (for example, as part of filebeat/metricbeat/ECS based indices)
|
||||
// to the data grid component which would significantly slow down the page.
|
||||
const [indexPatternFields, setIndexPatternFields] = useState<string[]>();
|
||||
const [dataViewFields, setDataViewFields] = useState<string[]>();
|
||||
const [timeRangeMs, setTimeRangeMs] = useState<TimeRangeMs | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -96,7 +96,7 @@ export const useIndexData = (
|
|||
setStatus(INDEX_STATUS.LOADING);
|
||||
|
||||
const esSearchRequest = {
|
||||
index: indexPattern.title,
|
||||
index: dataView.title,
|
||||
body: {
|
||||
fields: ['*'],
|
||||
_source: false,
|
||||
|
@ -116,13 +116,13 @@ export const useIndexData = (
|
|||
|
||||
// Get all field names for each returned doc and flatten it
|
||||
// to a list of unique field names used across all docs.
|
||||
const allDataViewFields = getFieldsFromKibanaIndexPattern(indexPattern);
|
||||
const allDataViewFields = getFieldsFromKibanaDataView(dataView);
|
||||
const populatedFields = [...new Set(docs.map(Object.keys).flat(1))]
|
||||
.filter((d) => allDataViewFields.includes(d))
|
||||
.sort();
|
||||
|
||||
setStatus(INDEX_STATUS.LOADED);
|
||||
setIndexPatternFields(populatedFields);
|
||||
setDataViewFields(populatedFields);
|
||||
} catch (e) {
|
||||
setErrorMessage(extractErrorMessage(e));
|
||||
setStatus(INDEX_STATUS.ERROR);
|
||||
|
@ -136,20 +136,20 @@ export const useIndexData = (
|
|||
// To be used for data grid column selection
|
||||
// and will be applied to doc and chart queries.
|
||||
const combinedRuntimeMappings = useMemo(
|
||||
() => getCombinedRuntimeMappings(indexPattern, runtimeMappings),
|
||||
[indexPattern, runtimeMappings]
|
||||
() => getCombinedRuntimeMappings(dataView, runtimeMappings),
|
||||
[dataView, runtimeMappings]
|
||||
);
|
||||
|
||||
// Available data grid columns, will be a combination of index pattern and runtime fields.
|
||||
const [columns, setColumns] = useState<MLEuiDataGridColumn[]>([]);
|
||||
useEffect(() => {
|
||||
if (Array.isArray(indexPatternFields)) {
|
||||
if (Array.isArray(dataViewFields)) {
|
||||
setColumns([
|
||||
...getIndexPatternColumns(indexPattern, indexPatternFields),
|
||||
...getDataViewColumns(dataView, dataViewFields),
|
||||
...(combinedRuntimeMappings ? getRuntimeFieldColumns(combinedRuntimeMappings) : []),
|
||||
]);
|
||||
}
|
||||
}, [indexPattern, indexPatternFields, combinedRuntimeMappings]);
|
||||
}, [dataView, dataViewFields, combinedRuntimeMappings]);
|
||||
|
||||
const dataGrid = useDataGrid(columns);
|
||||
|
||||
|
@ -175,19 +175,19 @@ export const useIndexData = (
|
|||
setErrorMessage('');
|
||||
setStatus(INDEX_STATUS.LOADING);
|
||||
|
||||
const timeFieldName = indexPattern.getTimeField()?.name;
|
||||
const timeFieldName = dataView.getTimeField()?.name;
|
||||
const sort: EsSorting = sortingColumns.reduce((s, column) => {
|
||||
s[column.id] = { order: column.direction };
|
||||
return s;
|
||||
}, {} as EsSorting);
|
||||
const esSearchRequest = {
|
||||
index: indexPattern.title,
|
||||
index: dataView.title,
|
||||
body: {
|
||||
query,
|
||||
from: pagination.pageIndex * pagination.pageSize,
|
||||
size: pagination.pageSize,
|
||||
fields: [
|
||||
...(indexPatternFields ?? []),
|
||||
...(dataViewFields ?? []),
|
||||
...(isRuntimeMappings(combinedRuntimeMappings)
|
||||
? Object.keys(combinedRuntimeMappings)
|
||||
: []),
|
||||
|
@ -246,22 +246,22 @@ export const useIndexData = (
|
|||
}
|
||||
}
|
||||
|
||||
if (indexPatternFields !== undefined && query !== undefined) {
|
||||
if (dataViewFields !== undefined && query !== undefined) {
|
||||
fetchIndexData();
|
||||
}
|
||||
// custom comparison
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
indexPattern.title,
|
||||
indexPatternFields,
|
||||
dataView.title,
|
||||
dataViewFields,
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
JSON.stringify([query, pagination, sortingColumns, combinedRuntimeMappings]),
|
||||
]);
|
||||
|
||||
const dataLoader = useMemo(
|
||||
() => new DataLoader(indexPattern, toastNotifications),
|
||||
() => new DataLoader(dataView, toastNotifications),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[indexPattern]
|
||||
[dataView]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -291,16 +291,16 @@ export const useIndexData = (
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
dataGrid.chartsVisible,
|
||||
indexPattern.title,
|
||||
dataView.title,
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
JSON.stringify([query, dataGrid.visibleColumns, runtimeMappings]),
|
||||
]);
|
||||
|
||||
const renderCellValue = useRenderCellValue(indexPattern, pagination, tableItems);
|
||||
const renderCellValue = useRenderCellValue(dataView, pagination, tableItems);
|
||||
|
||||
return {
|
||||
...dataGrid,
|
||||
indexPatternFields,
|
||||
dataViewFields,
|
||||
renderCellValue,
|
||||
timeRangeMs,
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ interface Props {
|
|||
destIndex?: string;
|
||||
}
|
||||
|
||||
export const IndexPatternPrompt: FC<Props> = ({ destIndex, color }) => {
|
||||
export const DataViewPrompt: FC<Props> = ({ destIndex, color }) => {
|
||||
const {
|
||||
services: {
|
||||
http: { basePath },
|
|
@ -5,4 +5,4 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { IndexPatternPrompt } from './index_pattern_prompt';
|
||||
export { DataViewPrompt } from './data_view_prompt';
|
|
@ -59,7 +59,7 @@ import { replaceStringTokens } from '../../../../../util/string_utils';
|
|||
import { parseInterval } from '../../../../../../../common/util/parse_interval';
|
||||
|
||||
import { ExpandableSection, ExpandableSectionProps, HEADER_ITEMS_LOADING } from '.';
|
||||
import { IndexPatternPrompt } from '../index_pattern_prompt';
|
||||
import { DataViewPrompt } from '../data_view_prompt';
|
||||
|
||||
const showingDocs = i18n.translate(
|
||||
'xpack.ml.dataframe.analytics.explorationResults.documentsShownHelpText',
|
||||
|
@ -121,9 +121,9 @@ const getResultsSectionHeaderItems = (
|
|||
interface ExpandableSectionResultsProps {
|
||||
colorRange?: ReturnType<typeof useColorRange>;
|
||||
indexData: UseIndexDataReturnType;
|
||||
indexPattern?: DataView;
|
||||
dataView?: DataView;
|
||||
jobConfig?: DataFrameAnalyticsConfig;
|
||||
needsDestIndexPattern: boolean;
|
||||
needsDestDataView: boolean;
|
||||
resultsField?: string;
|
||||
searchQuery: estypes.QueryDslQueryContainer;
|
||||
}
|
||||
|
@ -131,9 +131,9 @@ interface ExpandableSectionResultsProps {
|
|||
export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
||||
colorRange,
|
||||
indexData,
|
||||
indexPattern,
|
||||
dataView,
|
||||
jobConfig,
|
||||
needsDestIndexPattern,
|
||||
needsDestDataView,
|
||||
resultsField,
|
||||
searchQuery,
|
||||
}) => {
|
||||
|
@ -146,7 +146,7 @@ export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
|||
},
|
||||
} = useMlKibana();
|
||||
|
||||
const dataViewId = indexPattern?.id;
|
||||
const dataViewId = dataView?.id;
|
||||
|
||||
const discoverLocator = useMemo(
|
||||
() => share.url.locators.get('DISCOVER_APP_LOCATOR'),
|
||||
|
@ -206,7 +206,7 @@ export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
|||
|
||||
if (discoverLocator !== undefined) {
|
||||
const url = await discoverLocator.getRedirectUrl({
|
||||
indexPatternId: dataViewId,
|
||||
dataViewId,
|
||||
timeRange: data.query.timefilter.timefilter.getTime(),
|
||||
filters: data.query.filterManager.getFilters(),
|
||||
query: {
|
||||
|
@ -239,7 +239,7 @@ export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
|||
if (timeRangeInterval !== null) {
|
||||
// Create a copy of the record as we are adding properties into it.
|
||||
const record = cloneDeep(item);
|
||||
const timestamp = record[indexPattern!.timeFieldName!];
|
||||
const timestamp = record[dataView!.timeFieldName!];
|
||||
const configuredUrlValue = customUrl.url_value;
|
||||
|
||||
if (configuredUrlValue.includes('$earliest$')) {
|
||||
|
@ -373,9 +373,9 @@ export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
|||
|
||||
const resultsSectionContent = (
|
||||
<>
|
||||
{jobConfig !== undefined && needsDestIndexPattern && (
|
||||
{jobConfig !== undefined && needsDestDataView && (
|
||||
<div className="mlExpandableSection-contentPadding">
|
||||
<IndexPatternPrompt destIndex={jobConfig.dest.index} />
|
||||
<DataViewPrompt destIndex={jobConfig.dest.index} />
|
||||
</div>
|
||||
)}
|
||||
{jobConfig !== undefined &&
|
||||
|
@ -386,7 +386,7 @@ export const ExpandableSectionResults: FC<ExpandableSectionResultsProps> = ({
|
|||
</EuiText>
|
||||
)}
|
||||
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
|
||||
indexPattern !== undefined && (
|
||||
dataView !== undefined && (
|
||||
<>
|
||||
{columnsWithCharts.length > 0 &&
|
||||
(tableItems.length > 0 || status === INDEX_STATUS.LOADED) && (
|
||||
|
|
|
@ -35,7 +35,7 @@ import { LoadingPanel } from '../loading_panel';
|
|||
import { FeatureImportanceSummaryPanelProps } from '../total_feature_importance_summary/feature_importance_summary';
|
||||
import { useExplorationUrlState } from '../../hooks/use_exploration_url_state';
|
||||
import { ExplorationQueryBarProps } from '../exploration_query_bar/exploration_query_bar';
|
||||
import { IndexPatternPrompt } from '../index_pattern_prompt';
|
||||
import { DataViewPrompt } from '../data_view_prompt';
|
||||
|
||||
function getFilters(resultsField: string) {
|
||||
return {
|
||||
|
@ -84,15 +84,15 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
FeatureImportanceSummaryPanel,
|
||||
}) => {
|
||||
const {
|
||||
indexPattern,
|
||||
indexPatternErrorMessage,
|
||||
dataView,
|
||||
dataViewErrorMessage,
|
||||
isInitialized,
|
||||
isLoadingJobConfig,
|
||||
jobCapsServiceErrorMessage,
|
||||
jobConfig,
|
||||
jobConfigErrorMessage,
|
||||
jobStatus,
|
||||
needsDestIndexPattern,
|
||||
needsDestDataView,
|
||||
totalFeatureImportance,
|
||||
} = useResultsViewConfig(jobId);
|
||||
|
||||
|
@ -121,13 +121,13 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
const destIndex = getDestinationIndex(jobConfig);
|
||||
|
||||
const scatterplotFieldOptions = useScatterplotFieldOptions(
|
||||
indexPattern,
|
||||
dataView,
|
||||
jobConfig?.analyzed_fields?.includes,
|
||||
jobConfig?.analyzed_fields?.excludes,
|
||||
resultsField
|
||||
);
|
||||
|
||||
if (indexPatternErrorMessage !== undefined) {
|
||||
if (dataViewErrorMessage !== undefined) {
|
||||
return (
|
||||
<EuiPanel grow={false}>
|
||||
<EuiCallOut
|
||||
|
@ -138,10 +138,8 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
iconType="cross"
|
||||
>
|
||||
<p>
|
||||
{indexPatternErrorMessage}
|
||||
{needsDestIndexPattern ? (
|
||||
<IndexPatternPrompt destIndex={destIndex} color="text" />
|
||||
) : null}
|
||||
{dataViewErrorMessage}
|
||||
{needsDestDataView ? <DataViewPrompt destIndex={destIndex} color="text" /> : null}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
</EuiPanel>
|
||||
|
@ -170,7 +168,7 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
</>
|
||||
)}
|
||||
|
||||
{indexPattern !== undefined && jobConfig && (
|
||||
{dataView !== undefined && jobConfig && (
|
||||
<>
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -178,7 +176,7 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem>
|
||||
<ExplorationQueryBar
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
setSearchQuery={searchQueryUpdateHandler}
|
||||
query={query}
|
||||
filters={getFilters(jobConfig.dest.results_field!)}
|
||||
|
@ -227,7 +225,7 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
<ExpandableSectionSplom
|
||||
fields={scatterplotFieldOptions}
|
||||
index={jobConfig?.dest.index}
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
color={
|
||||
jobType === ANALYSIS_CONFIG_TYPE.REGRESSION ||
|
||||
jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION
|
||||
|
@ -242,13 +240,13 @@ export const ExplorationPageWrapper: FC<Props> = ({
|
|||
{isLoadingJobConfig === true && jobConfig === undefined && <LoadingPanel />}
|
||||
{isLoadingJobConfig === false &&
|
||||
jobConfig !== undefined &&
|
||||
indexPattern !== undefined &&
|
||||
dataView !== undefined &&
|
||||
isInitialized === true && (
|
||||
<ExplorationResultsTable
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
jobConfig={jobConfig}
|
||||
jobStatus={jobStatus}
|
||||
needsDestIndexPattern={needsDestIndexPattern}
|
||||
needsDestDataView={needsDestDataView}
|
||||
searchQuery={searchQuery}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -25,7 +25,7 @@ import { removeFilterFromQueryString } from '../../../../../explorer/explorer_ut
|
|||
import { useMlKibana } from '../../../../../contexts/kibana';
|
||||
|
||||
export interface ExplorationQueryBarProps {
|
||||
indexPattern: DataView;
|
||||
dataView: DataView;
|
||||
setSearchQuery: (update: {
|
||||
queryString: string;
|
||||
query?: estypes.QueryDslQueryContainer;
|
||||
|
@ -41,7 +41,7 @@ export interface ExplorationQueryBarProps {
|
|||
}
|
||||
|
||||
export const ExplorationQueryBar: FC<ExplorationQueryBarProps> = ({
|
||||
indexPattern,
|
||||
dataView,
|
||||
setSearchQuery,
|
||||
filters,
|
||||
query,
|
||||
|
@ -99,7 +99,7 @@ export const ExplorationQueryBar: FC<ExplorationQueryBarProps> = ({
|
|||
case SEARCH_QUERY_LANGUAGE.KUERY:
|
||||
convertedQuery = toElasticsearchQuery(
|
||||
fromKueryExpression(query.query as string),
|
||||
indexPattern
|
||||
dataView
|
||||
);
|
||||
break;
|
||||
case SEARCH_QUERY_LANGUAGE.LUCENE:
|
||||
|
@ -181,7 +181,7 @@ export const ExplorationQueryBar: FC<ExplorationQueryBarProps> = ({
|
|||
<QueryStringInput
|
||||
bubbleSubmitEvent={false}
|
||||
query={searchInput}
|
||||
indexPatterns={[indexPattern]}
|
||||
indexPatterns={[dataView]}
|
||||
onChange={searchChangeHandler}
|
||||
onSubmit={searchSubmitHandler}
|
||||
placeholder={
|
||||
|
|
|
@ -23,15 +23,15 @@ import { ExpandableSectionResults } from '../expandable_section';
|
|||
import { useExplorationResults } from './use_exploration_results';
|
||||
|
||||
interface Props {
|
||||
indexPattern: DataView;
|
||||
dataView: DataView;
|
||||
jobConfig: DataFrameAnalyticsConfig;
|
||||
jobStatus?: DataFrameTaskStateType;
|
||||
needsDestIndexPattern: boolean;
|
||||
needsDestDataView: boolean;
|
||||
searchQuery: ResultsSearchQuery;
|
||||
}
|
||||
|
||||
export const ExplorationResultsTable: FC<Props> = React.memo(
|
||||
({ indexPattern, jobConfig, needsDestIndexPattern, searchQuery }) => {
|
||||
({ dataView, jobConfig, needsDestDataView, searchQuery }) => {
|
||||
const {
|
||||
services: {
|
||||
mlServices: { mlApiServices },
|
||||
|
@ -39,7 +39,7 @@ export const ExplorationResultsTable: FC<Props> = React.memo(
|
|||
} = useMlKibana();
|
||||
|
||||
const classificationData = useExplorationResults(
|
||||
indexPattern,
|
||||
dataView,
|
||||
jobConfig,
|
||||
searchQuery,
|
||||
getToastNotifications(),
|
||||
|
@ -54,10 +54,10 @@ export const ExplorationResultsTable: FC<Props> = React.memo(
|
|||
<div data-test-subj="mlDFAnalyticsExplorationTablePanel">
|
||||
<ExpandableSectionResults
|
||||
indexData={classificationData}
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
resultsField={jobConfig?.dest.results_field}
|
||||
jobConfig={jobConfig}
|
||||
needsDestIndexPattern={needsDestIndexPattern}
|
||||
needsDestDataView={needsDestDataView}
|
||||
searchQuery={searchQuery}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -43,7 +43,7 @@ import { useTrainedModelsApiService } from '../../../../../services/ml_api_servi
|
|||
import { useExplorationDataGrid } from './use_exploration_data_grid';
|
||||
|
||||
export const useExplorationResults = (
|
||||
indexPattern: DataView | undefined,
|
||||
dataView: DataView | undefined,
|
||||
jobConfig: DataFrameAnalyticsConfig | undefined,
|
||||
searchQuery: estypes.QueryDslQueryContainer,
|
||||
toastNotifications: CoreSetup['notifications']['toasts'],
|
||||
|
@ -54,7 +54,7 @@ export const useExplorationResults = (
|
|||
const trainedModelsApiService = useTrainedModelsApiService();
|
||||
|
||||
const needsDestIndexFields =
|
||||
indexPattern !== undefined && indexPattern.title === jobConfig?.source.index[0];
|
||||
dataView !== undefined && dataView.title === jobConfig?.source.index[0];
|
||||
|
||||
const columns: EuiDataGridColumn[] = [];
|
||||
|
||||
|
@ -90,10 +90,9 @@ export const useExplorationResults = (
|
|||
}, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]);
|
||||
|
||||
const dataLoader = useMemo(
|
||||
() =>
|
||||
indexPattern !== undefined ? new DataLoader(indexPattern, toastNotifications) : undefined,
|
||||
() => (dataView !== undefined ? new DataLoader(dataView, toastNotifications) : undefined),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[indexPattern]
|
||||
[dataView]
|
||||
);
|
||||
|
||||
const fetchColumnChartsData = async function () {
|
||||
|
@ -179,7 +178,7 @@ export const useExplorationResults = (
|
|||
|
||||
const resultsField = jobConfig?.dest.results_field ?? DEFAULT_RESULTS_FIELD;
|
||||
const renderCellValue = useRenderCellValue(
|
||||
indexPattern,
|
||||
dataView,
|
||||
dataGrid.pagination,
|
||||
dataGrid.tableItems,
|
||||
resultsField
|
||||
|
|
|
@ -37,7 +37,7 @@ export const JobConfigErrorCallout: FC<Props> = ({
|
|||
application: { getUrlForApp },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const containsIndexPatternLink =
|
||||
const containsDataViewLink =
|
||||
typeof jobCapsServiceErrorMessage === 'string' &&
|
||||
jobCapsServiceErrorMessage.includes('locate that index-pattern') &&
|
||||
jobCapsServiceErrorMessage.includes('click here to re-create');
|
||||
|
@ -45,7 +45,7 @@ export const JobConfigErrorCallout: FC<Props> = ({
|
|||
const message = (
|
||||
<p>{jobConfigErrorMessage ? jobConfigErrorMessage : jobCapsServiceErrorMessage}</p>
|
||||
);
|
||||
const newIndexPatternUrl = useMemo(
|
||||
const newDataViewUrl = useMemo(
|
||||
() =>
|
||||
getUrlForApp('management', {
|
||||
path: 'kibana/indexPatterns',
|
||||
|
@ -54,8 +54,8 @@ export const JobConfigErrorCallout: FC<Props> = ({
|
|||
[]
|
||||
);
|
||||
|
||||
const calloutBody = containsIndexPatternLink ? (
|
||||
<EuiLink href={newIndexPatternUrl} target="_blank">
|
||||
const calloutBody = containsDataViewLink ? (
|
||||
<EuiLink href={newDataViewUrl} target="_blank">
|
||||
{message}
|
||||
</EuiLink>
|
||||
) : (
|
||||
|
|
|
@ -33,7 +33,7 @@ import { getFeatureCount } from './common';
|
|||
import { useOutlierData } from './use_outlier_data';
|
||||
import { useExplorationUrlState } from '../../hooks/use_exploration_url_state';
|
||||
import { ExplorationQueryBarProps } from '../exploration_query_bar/exploration_query_bar';
|
||||
import { IndexPatternPrompt } from '../index_pattern_prompt';
|
||||
import { DataViewPrompt } from '../data_view_prompt';
|
||||
|
||||
export type TableItem = Record<string, any>;
|
||||
|
||||
|
@ -42,12 +42,12 @@ interface ExplorationProps {
|
|||
}
|
||||
|
||||
export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) => {
|
||||
const { indexPattern, indexPatternErrorMessage, jobConfig, needsDestIndexPattern } =
|
||||
const { dataView, dataViewErrorMessage, jobConfig, needsDestDataView } =
|
||||
useResultsViewConfig(jobId);
|
||||
const [pageUrlState, setPageUrlState] = useExplorationUrlState();
|
||||
const [searchQuery, setSearchQuery] =
|
||||
useState<estypes.QueryDslQueryContainer>(defaultSearchQuery);
|
||||
const outlierData = useOutlierData(indexPattern, jobConfig, searchQuery);
|
||||
const outlierData = useOutlierData(dataView, jobConfig, searchQuery);
|
||||
|
||||
const searchQueryUpdateHandler: ExplorationQueryBarProps['setSearchQuery'] = useCallback(
|
||||
(update) => {
|
||||
|
@ -81,20 +81,20 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
// If feature influence was enabled for the legacy job we'll show a callout
|
||||
// with some additional information for a workaround.
|
||||
const showLegacyFeatureInfluenceFormatCallout =
|
||||
!needsDestIndexPattern &&
|
||||
!needsDestDataView &&
|
||||
isOutlierAnalysis(jobConfig?.analysis) &&
|
||||
jobConfig?.analysis.outlier_detection.compute_feature_influence === true &&
|
||||
columnsWithCharts.findIndex((d) => d.id === `${resultsField}.${FEATURE_INFLUENCE}`) === -1;
|
||||
|
||||
const scatterplotFieldOptions = useScatterplotFieldOptions(
|
||||
indexPattern,
|
||||
dataView,
|
||||
jobConfig?.analyzed_fields?.includes,
|
||||
jobConfig?.analyzed_fields?.excludes,
|
||||
resultsField
|
||||
);
|
||||
const destIndex = getDestinationIndex(jobConfig);
|
||||
|
||||
if (indexPatternErrorMessage !== undefined) {
|
||||
if (dataViewErrorMessage !== undefined) {
|
||||
return (
|
||||
<EuiPanel grow={false} hasShadow={false} hasBorder>
|
||||
<EuiCallOut
|
||||
|
@ -105,10 +105,8 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
iconType="cross"
|
||||
>
|
||||
<p>
|
||||
{indexPatternErrorMessage}
|
||||
{needsDestIndexPattern ? (
|
||||
<IndexPatternPrompt destIndex={destIndex} color="text" />
|
||||
) : null}
|
||||
{dataViewErrorMessage}
|
||||
{needsDestDataView ? <DataViewPrompt destIndex={destIndex} color="text" /> : null}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
</EuiPanel>
|
||||
|
@ -124,10 +122,10 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
</>
|
||||
)}
|
||||
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
|
||||
indexPattern !== undefined && (
|
||||
dataView !== undefined && (
|
||||
<>
|
||||
<ExplorationQueryBar
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
setSearchQuery={searchQueryUpdateHandler}
|
||||
query={query}
|
||||
/>
|
||||
|
@ -165,9 +163,9 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
showColorRange && !showLegacyFeatureInfluenceFormatCallout ? colorRange : undefined
|
||||
}
|
||||
indexData={outlierData}
|
||||
indexPattern={indexPattern}
|
||||
dataView={dataView}
|
||||
jobConfig={jobConfig}
|
||||
needsDestIndexPattern={needsDestIndexPattern}
|
||||
needsDestDataView={needsDestDataView}
|
||||
searchQuery={searchQuery}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -41,17 +41,17 @@ import { getFeatureCount, getOutlierScoreFieldName } from './common';
|
|||
import { useExplorationDataGrid } from '../exploration_results_table/use_exploration_data_grid';
|
||||
|
||||
export const useOutlierData = (
|
||||
indexPattern: DataView | undefined,
|
||||
dataView: DataView | undefined,
|
||||
jobConfig: DataFrameAnalyticsConfig | undefined,
|
||||
searchQuery: estypes.QueryDslQueryContainer
|
||||
): UseIndexDataReturnType => {
|
||||
const needsDestIndexFields =
|
||||
indexPattern !== undefined && indexPattern.title === jobConfig?.source.index[0];
|
||||
dataView !== undefined && dataView.title === jobConfig?.source.index[0];
|
||||
|
||||
const columns = useMemo(() => {
|
||||
const newColumns: EuiDataGridColumn[] = [];
|
||||
|
||||
if (jobConfig !== undefined && indexPattern !== undefined) {
|
||||
if (jobConfig !== undefined && dataView !== undefined) {
|
||||
const resultsField = jobConfig.dest.results_field;
|
||||
const { fieldTypes } = getIndexFields(jobConfig, needsDestIndexFields);
|
||||
newColumns.push(
|
||||
|
@ -63,7 +63,7 @@ export const useOutlierData = (
|
|||
|
||||
return newColumns;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jobConfig, indexPattern]);
|
||||
}, [jobConfig, dataView]);
|
||||
|
||||
const dataGrid = useExplorationDataGrid(
|
||||
columns,
|
||||
|
@ -95,11 +95,8 @@ export const useOutlierData = (
|
|||
}, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]);
|
||||
|
||||
const dataLoader = useMemo(
|
||||
() =>
|
||||
indexPattern !== undefined
|
||||
? new DataLoader(indexPattern, getToastNotifications())
|
||||
: undefined,
|
||||
[indexPattern]
|
||||
() => (dataView !== undefined ? new DataLoader(dataView, getToastNotifications()) : undefined),
|
||||
[dataView]
|
||||
);
|
||||
|
||||
const fetchColumnChartsData = async function () {
|
||||
|
@ -146,7 +143,7 @@ export const useOutlierData = (
|
|||
);
|
||||
|
||||
const renderCellValue = useRenderCellValue(
|
||||
indexPattern,
|
||||
dataView,
|
||||
dataGrid.pagination,
|
||||
dataGrid.tableItems,
|
||||
jobConfig?.dest.results_field ?? DEFAULT_RESULTS_FIELD,
|
||||
|
|
|
@ -21,12 +21,12 @@ export const DeleteActionModal: FC<DeleteAction> = ({
|
|||
closeModal,
|
||||
deleteAndCloseModal,
|
||||
deleteTargetIndex,
|
||||
deleteIndexPattern,
|
||||
indexPatternExists,
|
||||
deleteDataView,
|
||||
dataViewExists,
|
||||
isLoading,
|
||||
item,
|
||||
toggleDeleteIndex,
|
||||
toggleDeleteIndexPattern,
|
||||
toggleDeleteDataView,
|
||||
userCanDeleteIndex,
|
||||
userCanDeleteDataView,
|
||||
}) => {
|
||||
|
@ -77,15 +77,15 @@ export const DeleteActionModal: FC<DeleteAction> = ({
|
|||
)}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
{userCanDeleteIndex && indexPatternExists && (
|
||||
{userCanDeleteIndex && dataViewExists && (
|
||||
<EuiSwitch
|
||||
data-test-subj="mlAnalyticsJobDeleteIndexPatternSwitch"
|
||||
data-test-subj="mlAnalyticsJobDeleteDataViewSwitch"
|
||||
label={i18n.translate('xpack.ml.dataframe.analyticsList.deleteTargetDataViewTitle', {
|
||||
defaultMessage: 'Delete data view {dataView}',
|
||||
values: { dataView: indexName },
|
||||
})}
|
||||
checked={deleteIndexPattern}
|
||||
onChange={toggleDeleteIndexPattern}
|
||||
checked={deleteDataView}
|
||||
onChange={toggleDeleteDataView}
|
||||
disabled={userCanDeleteDataView === false}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -99,7 +99,7 @@ describe('DeleteAction', () => {
|
|||
fireEvent.click(deleteButton);
|
||||
expect(getByTestId('mlAnalyticsJobDeleteModal')).toBeInTheDocument();
|
||||
expect(queryByTestId('mlAnalyticsJobDeleteIndexSwitch')).toBeNull();
|
||||
expect(queryByTestId('mlAnalyticsJobDeleteIndexPatternSwitch')).toBeNull();
|
||||
expect(queryByTestId('mlAnalyticsJobDeleteDataViewSwitch')).toBeNull();
|
||||
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
|
|
@ -42,10 +42,10 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
const [isDeleteJobCheckModalVisible, setDeleteJobCheckModalVisible] = useState<boolean>(false);
|
||||
const [deleteItem, setDeleteItem] = useState(false);
|
||||
const [deleteTargetIndex, setDeleteTargetIndex] = useState<boolean>(true);
|
||||
const [deleteIndexPattern, setDeleteIndexPattern] = useState<boolean>(true);
|
||||
const [deleteDataView, setDeleteDataView] = useState<boolean>(true);
|
||||
const [userCanDeleteIndex, setUserCanDeleteIndex] = useState<boolean>(false);
|
||||
const [userCanDeleteDataView, setUserCanDeleteDataView] = useState<boolean>(false);
|
||||
const [indexPatternExists, setIndexPatternExists] = useState<boolean>(false);
|
||||
const [dataViewExists, setDataViewExists] = useState<boolean>(false);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const {
|
||||
|
@ -57,13 +57,13 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
|
||||
const toastNotificationService = useToastNotificationService();
|
||||
|
||||
const checkIndexPatternExists = async () => {
|
||||
const checkDataViewExists = async () => {
|
||||
try {
|
||||
const dv = (await dataViews.getIdsWithTitle()).find(({ title }) => title === indexName);
|
||||
if (dv !== undefined) {
|
||||
setIndexPatternExists(true);
|
||||
setDataViewExists(true);
|
||||
} else {
|
||||
setIndexPatternExists(false);
|
||||
setDataViewExists(false);
|
||||
}
|
||||
setIsLoading(false);
|
||||
} catch (e) {
|
||||
|
@ -93,7 +93,7 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
capabilities.indexPatterns.save === true;
|
||||
setUserCanDeleteDataView(canDeleteDataView);
|
||||
if (canDeleteDataView === false) {
|
||||
setDeleteIndexPattern(false);
|
||||
setDeleteDataView(false);
|
||||
}
|
||||
} catch (e) {
|
||||
const error = extractErrorMessage(e);
|
||||
|
@ -116,7 +116,7 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
setIsLoading(true);
|
||||
// Check if a data view exists corresponding to current DFA job
|
||||
// if data view does exist, show it to user
|
||||
checkIndexPatternExists();
|
||||
checkDataViewExists();
|
||||
// Check if an user has permission to delete the index & data view
|
||||
checkUserIndexPermission();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
@ -129,12 +129,12 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
setModalVisible(false);
|
||||
|
||||
if (item !== undefined) {
|
||||
if ((userCanDeleteIndex && deleteTargetIndex) || (userCanDeleteIndex && deleteIndexPattern)) {
|
||||
if ((userCanDeleteIndex && deleteTargetIndex) || (userCanDeleteIndex && deleteDataView)) {
|
||||
deleteAnalyticsAndDestIndex(
|
||||
item.config,
|
||||
item.stats,
|
||||
deleteTargetIndex,
|
||||
indexPatternExists && deleteIndexPattern,
|
||||
dataViewExists && deleteDataView,
|
||||
toastNotificationService
|
||||
);
|
||||
} else {
|
||||
|
@ -143,7 +143,7 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
}
|
||||
};
|
||||
const toggleDeleteIndex = () => setDeleteTargetIndex(!deleteTargetIndex);
|
||||
const toggleDeleteIndexPattern = () => setDeleteIndexPattern(!deleteIndexPattern);
|
||||
const toggleDeleteDataView = () => setDeleteDataView(!deleteDataView);
|
||||
|
||||
const openModal = (newItem: DataFrameAnalyticsListRowEssentials) => {
|
||||
setItem(newItem);
|
||||
|
@ -181,9 +181,9 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
closeModal,
|
||||
deleteAndCloseModal,
|
||||
deleteTargetIndex,
|
||||
deleteIndexPattern,
|
||||
deleteDataView,
|
||||
deleteItem,
|
||||
indexPatternExists,
|
||||
dataViewExists,
|
||||
isDeleteJobCheckModalVisible,
|
||||
isModalVisible,
|
||||
isLoading,
|
||||
|
@ -192,7 +192,7 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
|
|||
openModal,
|
||||
openDeleteJobCheckModal,
|
||||
toggleDeleteIndex,
|
||||
toggleDeleteIndexPattern,
|
||||
toggleDeleteDataView,
|
||||
userCanDeleteIndex,
|
||||
userCanDeleteDataView,
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ export const SourceSelection: FC = () => {
|
|||
type: 'index-pattern',
|
||||
getIconForSavedObject: () => 'indexPatternApp',
|
||||
name: i18n.translate(
|
||||
'xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.indexPattern',
|
||||
'xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.dataView',
|
||||
{
|
||||
defaultMessage: 'Data view',
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export enum ACTION {
|
|||
RESET_FORM,
|
||||
SET_ADVANCED_EDITOR_RAW_STRING,
|
||||
SET_FORM_STATE,
|
||||
SET_INDEX_PATTERN_TITLES,
|
||||
SET_DATA_VIEW_TITLES,
|
||||
SET_IS_JOB_CREATED,
|
||||
SET_IS_JOB_STARTED,
|
||||
SET_IS_MODAL_BUTTON_DISABLED,
|
||||
|
@ -51,9 +51,9 @@ export type Action =
|
|||
}
|
||||
| { type: ACTION.SET_FORM_STATE; payload: Partial<State['form']> }
|
||||
| {
|
||||
type: ACTION.SET_INDEX_PATTERN_TITLES;
|
||||
type: ACTION.SET_DATA_VIEW_TITLES;
|
||||
payload: {
|
||||
indexPatternsMap: SourceIndexMap;
|
||||
dataViewsMap: SourceIndexMap;
|
||||
};
|
||||
}
|
||||
| { type: ACTION.SET_IS_JOB_CREATED; isJobCreated: State['isJobCreated'] }
|
||||
|
|
|
@ -39,7 +39,7 @@ const getMockState = ({
|
|||
jobIdEmpty: false,
|
||||
jobIdValid: true,
|
||||
jobIdExists: false,
|
||||
createIndexPattern: false,
|
||||
createDataView: false,
|
||||
},
|
||||
jobConfig: {
|
||||
source: { index },
|
||||
|
|
|
@ -148,7 +148,7 @@ export const validateNumTopFeatureImportanceValues = (
|
|||
};
|
||||
|
||||
export const validateAdvancedEditor = (state: State): State => {
|
||||
const { jobIdEmpty, jobIdValid, jobIdExists, jobType, createIndexPattern } = state.form;
|
||||
const { jobIdEmpty, jobIdValid, jobIdExists, jobType, createDataView } = state.form;
|
||||
const { jobConfig } = state;
|
||||
|
||||
state.advancedEditorMessages = [];
|
||||
|
@ -161,8 +161,7 @@ export const validateAdvancedEditor = (state: State): State => {
|
|||
const destinationIndexName = jobConfig?.dest?.index ?? '';
|
||||
const destinationIndexNameEmpty = destinationIndexName === '';
|
||||
const destinationIndexNameValid = isValidIndexName(destinationIndexName);
|
||||
const destinationIndexPatternTitleExists =
|
||||
state.indexPatternsMap[destinationIndexName] !== undefined;
|
||||
const destinationDataViewTitleExists = state.dataViewsMap[destinationIndexName] !== undefined;
|
||||
|
||||
const analyzedFields = jobConfig?.analyzed_fields?.includes || [];
|
||||
|
||||
|
@ -294,7 +293,7 @@ export const validateAdvancedEditor = (state: State): State => {
|
|||
),
|
||||
message: '',
|
||||
});
|
||||
} else if (destinationIndexPatternTitleExists && !createIndexPattern) {
|
||||
} else if (destinationDataViewTitleExists && !createDataView) {
|
||||
state.advancedEditorMessages.push({
|
||||
error: i18n.translate(
|
||||
'xpack.ml.dataframe.analytics.create.advancedEditorMessage.destinationIndexNameExistsWarn',
|
||||
|
@ -360,7 +359,7 @@ export const validateAdvancedEditor = (state: State): State => {
|
|||
});
|
||||
}
|
||||
|
||||
state.form.destinationIndexPatternTitleExists = destinationIndexPatternTitleExists;
|
||||
state.form.destinationDataViewTitleExists = destinationDataViewTitleExists;
|
||||
|
||||
state.isValid =
|
||||
includesValid &&
|
||||
|
@ -377,7 +376,7 @@ export const validateAdvancedEditor = (state: State): State => {
|
|||
!dependentVariableEmpty &&
|
||||
!modelMemoryLimitEmpty &&
|
||||
(numTopFeatureImportanceValuesValid || jobType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION) &&
|
||||
(!destinationIndexPatternTitleExists || !createIndexPattern);
|
||||
(!destinationDataViewTitleExists || !createDataView);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
@ -425,8 +424,8 @@ const validateForm = (state: State): State => {
|
|||
sourceIndexNameValid,
|
||||
destinationIndexNameEmpty,
|
||||
destinationIndexNameValid,
|
||||
destinationIndexPatternTitleExists,
|
||||
createIndexPattern,
|
||||
destinationDataViewTitleExists,
|
||||
createDataView,
|
||||
dependentVariable,
|
||||
modelMemoryLimit,
|
||||
numTopFeatureImportanceValuesValid,
|
||||
|
@ -458,7 +457,7 @@ const validateForm = (state: State): State => {
|
|||
destinationIndexNameValid &&
|
||||
!dependentVariableEmpty &&
|
||||
(numTopFeatureImportanceValuesValid || jobType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION) &&
|
||||
(!destinationIndexPatternTitleExists || !createIndexPattern);
|
||||
(!destinationDataViewTitleExists || !createDataView);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
@ -513,8 +512,8 @@ export function reducer(state: State, action: Action): State {
|
|||
if (action.payload.destinationIndex !== undefined) {
|
||||
newFormState.destinationIndexNameEmpty = newFormState.destinationIndex === '';
|
||||
newFormState.destinationIndexNameValid = isValidIndexName(newFormState.destinationIndex);
|
||||
newFormState.destinationIndexPatternTitleExists =
|
||||
state.indexPatternsMap[newFormState.destinationIndex] !== undefined;
|
||||
newFormState.destinationDataViewTitleExists =
|
||||
state.dataViewsMap[newFormState.destinationIndex] !== undefined;
|
||||
}
|
||||
|
||||
if (action.payload.jobId !== undefined) {
|
||||
|
@ -541,13 +540,13 @@ export function reducer(state: State, action: Action): State {
|
|||
? validateAdvancedEditor({ ...state, form: newFormState })
|
||||
: validateForm({ ...state, form: newFormState });
|
||||
|
||||
case ACTION.SET_INDEX_PATTERN_TITLES: {
|
||||
case ACTION.SET_DATA_VIEW_TITLES: {
|
||||
const newState = {
|
||||
...state,
|
||||
...action.payload,
|
||||
};
|
||||
newState.form.destinationIndexPatternTitleExists =
|
||||
newState.indexPatternsMap[newState.form.destinationIndex] !== undefined;
|
||||
newState.form.destinationDataViewTitleExists =
|
||||
newState.dataViewsMap[newState.form.destinationIndex] !== undefined;
|
||||
return newState;
|
||||
}
|
||||
|
||||
|
@ -591,8 +590,8 @@ export function reducer(state: State, action: Action): State {
|
|||
|
||||
formState.destinationIndexNameEmpty = formState.destinationIndex === '';
|
||||
formState.destinationIndexNameValid = isValidIndexName(formState.destinationIndex || '');
|
||||
formState.destinationIndexPatternTitleExists =
|
||||
state.indexPatternsMap[formState.destinationIndex || ''] !== undefined;
|
||||
formState.destinationDataViewTitleExists =
|
||||
state.dataViewsMap[formState.destinationIndex || ''] !== undefined;
|
||||
|
||||
if (formState.numTopFeatureImportanceValues !== undefined) {
|
||||
formState.numTopFeatureImportanceValuesValid = validateNumTopFeatureImportanceValues(
|
||||
|
|
|
@ -35,13 +35,10 @@ export const UNSET_CONFIG_ITEM = '--';
|
|||
|
||||
export type EsIndexName = string;
|
||||
export type DependentVariable = string;
|
||||
export type IndexPatternTitle = string;
|
||||
export type DataViewTitle = string;
|
||||
export type AnalyticsJobType = DataFrameAnalysisConfigType | undefined;
|
||||
type IndexPatternId = string;
|
||||
export type SourceIndexMap = Record<
|
||||
IndexPatternTitle,
|
||||
{ label: IndexPatternTitle; value: IndexPatternId }
|
||||
>;
|
||||
type DataViewId = string;
|
||||
export type SourceIndexMap = Record<DataViewTitle, { label: DataViewTitle; value: DataViewId }>;
|
||||
|
||||
export interface FormMessage {
|
||||
error?: string;
|
||||
|
@ -55,7 +52,7 @@ export interface State {
|
|||
form: {
|
||||
alpha: undefined | number;
|
||||
computeFeatureInfluence: string;
|
||||
createIndexPattern: boolean;
|
||||
createDataView: boolean;
|
||||
classAssignmentObjective: undefined | string;
|
||||
dependentVariable: DependentVariable;
|
||||
description: string;
|
||||
|
@ -63,7 +60,7 @@ export interface State {
|
|||
destinationIndexNameExists: boolean;
|
||||
destinationIndexNameEmpty: boolean;
|
||||
destinationIndexNameValid: boolean;
|
||||
destinationIndexPatternTitleExists: boolean;
|
||||
destinationDataViewTitleExists: boolean;
|
||||
downsampleFactor: undefined | number;
|
||||
earlyStoppingEnabled: undefined | boolean;
|
||||
eta: undefined | number;
|
||||
|
@ -120,7 +117,7 @@ export interface State {
|
|||
useEstimatedMml: boolean;
|
||||
};
|
||||
disabled: boolean;
|
||||
indexPatternsMap: SourceIndexMap;
|
||||
dataViewsMap: SourceIndexMap;
|
||||
isAdvancedEditorEnabled: boolean;
|
||||
isAdvancedEditorValidJson: boolean;
|
||||
hasSwitchedToEditor: boolean;
|
||||
|
@ -141,7 +138,7 @@ export const getInitialState = (): State => ({
|
|||
form: {
|
||||
alpha: undefined,
|
||||
computeFeatureInfluence: 'true',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
classAssignmentObjective: undefined,
|
||||
dependentVariable: '',
|
||||
description: '',
|
||||
|
@ -149,7 +146,7 @@ export const getInitialState = (): State => ({
|
|||
destinationIndexNameExists: false,
|
||||
destinationIndexNameEmpty: true,
|
||||
destinationIndexNameValid: false,
|
||||
destinationIndexPatternTitleExists: false,
|
||||
destinationDataViewTitleExists: false,
|
||||
earlyStoppingEnabled: undefined,
|
||||
downsampleFactor: undefined,
|
||||
eta: undefined,
|
||||
|
@ -210,7 +207,7 @@ export const getInitialState = (): State => ({
|
|||
!mlNodesAvailable() ||
|
||||
!checkPermission('canCreateDataFrameAnalytics') ||
|
||||
!checkPermission('canStartStopDataFrameAnalytics'),
|
||||
indexPatternsMap: {},
|
||||
dataViewsMap: {},
|
||||
isAdvancedEditorEnabled: false,
|
||||
isAdvancedEditorValidJson: true,
|
||||
hasSwitchedToEditor: false,
|
||||
|
|
|
@ -59,7 +59,7 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
|
|||
const { refresh } = useRefreshAnalyticsList();
|
||||
|
||||
const { form, jobConfig, isAdvancedEditorEnabled } = state;
|
||||
const { createIndexPattern, jobId } = form;
|
||||
const { createDataView, jobId } = form;
|
||||
let { destinationIndex } = form;
|
||||
|
||||
const addRequestMessage = (requestMessage: FormMessage) =>
|
||||
|
@ -73,8 +73,8 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
|
|||
const setAdvancedEditorRawString = (advancedEditorRawString: string) =>
|
||||
dispatch({ type: ACTION.SET_ADVANCED_EDITOR_RAW_STRING, advancedEditorRawString });
|
||||
|
||||
const setIndexPatternTitles = (payload: { indexPatternsMap: SourceIndexMap }) =>
|
||||
dispatch({ type: ACTION.SET_INDEX_PATTERN_TITLES, payload });
|
||||
const setDataViewTitles = (payload: { dataViewsMap: SourceIndexMap }) =>
|
||||
dispatch({ type: ACTION.SET_DATA_VIEW_TITLES, payload });
|
||||
|
||||
const setIsJobCreated = (isJobCreated: boolean) =>
|
||||
dispatch({ type: ACTION.SET_IS_JOB_CREATED, isJobCreated });
|
||||
|
@ -110,7 +110,7 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
|
|||
),
|
||||
});
|
||||
setIsJobCreated(true);
|
||||
if (createIndexPattern) {
|
||||
if (createDataView) {
|
||||
createKibanaDataView(destinationIndex, dataViews, form.timeFieldName, addRequestMessage);
|
||||
}
|
||||
refresh();
|
||||
|
@ -132,17 +132,17 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
|
|||
const prepareFormValidation = async () => {
|
||||
try {
|
||||
// Set the existing data view names.
|
||||
const indexPatternsMap: SourceIndexMap = {};
|
||||
const dataViewsMap: SourceIndexMap = {};
|
||||
const savedObjects = (await dataViews.getCache()) || [];
|
||||
savedObjects.forEach((obj) => {
|
||||
const title = obj?.attributes?.title;
|
||||
if (title !== undefined) {
|
||||
const id = obj?.id || '';
|
||||
indexPatternsMap[title] = { label: title, value: id };
|
||||
dataViewsMap[title] = { label: title, value: id };
|
||||
}
|
||||
});
|
||||
setIndexPatternTitles({
|
||||
indexPatternsMap,
|
||||
setDataViewTitles({
|
||||
dataViewsMap,
|
||||
});
|
||||
} catch (e) {
|
||||
addRequestMessage({
|
||||
|
|
|
@ -48,7 +48,7 @@ export const deleteAnalyticsAndDestIndex = async (
|
|||
analyticsConfig: DataFrameAnalyticsListRow['config'],
|
||||
analyticsStats: DataFrameAnalyticsListRow['stats'],
|
||||
deleteDestIndex: boolean,
|
||||
deleteDestIndexPattern: boolean,
|
||||
deleteDestDataView: boolean,
|
||||
toastNotificationService: ToastNotificationService
|
||||
) => {
|
||||
const destinationIndex = analyticsConfig.dest.index;
|
||||
|
@ -59,7 +59,7 @@ export const deleteAnalyticsAndDestIndex = async (
|
|||
const status = await ml.dataFrameAnalytics.deleteDataFrameAnalyticsAndDestIndex(
|
||||
analyticsConfig.id,
|
||||
deleteDestIndex,
|
||||
deleteDestIndexPattern
|
||||
deleteDestDataView
|
||||
);
|
||||
if (status.analyticsJobDeleted?.success) {
|
||||
toastNotificationService.displaySuccessToast(
|
||||
|
@ -97,7 +97,7 @@ export const deleteAnalyticsAndDestIndex = async (
|
|||
);
|
||||
}
|
||||
|
||||
if (status.destIndexPatternDeleted?.success) {
|
||||
if (status.destDataViewDeleted?.success) {
|
||||
toastNotificationService.displaySuccessToast(
|
||||
i18n.translate(
|
||||
'xpack.ml.dataframe.analyticsList.deleteAnalyticsWithDataViewSuccessMessage',
|
||||
|
@ -108,8 +108,8 @@ export const deleteAnalyticsAndDestIndex = async (
|
|||
)
|
||||
);
|
||||
}
|
||||
if (status.destIndexPatternDeleted?.error) {
|
||||
const error = extractErrorMessage(status.destIndexPatternDeleted.error);
|
||||
if (status.destDataViewDeleted?.error) {
|
||||
const error = extractErrorMessage(status.destDataViewDeleted.error);
|
||||
toastNotificationService.displayDangerToast(
|
||||
i18n.translate('xpack.ml.dataframe.analyticsList.deleteAnalyticsWithDataViewErrorMessage', {
|
||||
defaultMessage: 'An error occurred deleting data view {destinationIndex}: {error}',
|
||||
|
|
|
@ -49,7 +49,7 @@ export interface DeleteDataFrameAnalyticsWithIndexResponse {
|
|||
acknowledged: boolean;
|
||||
analyticsJobDeleted: DeleteDataFrameAnalyticsWithIndexStatus;
|
||||
destIndexDeleted: DeleteDataFrameAnalyticsWithIndexStatus;
|
||||
destIndexPatternDeleted: DeleteDataFrameAnalyticsWithIndexStatus;
|
||||
destDataViewDeleted: DeleteDataFrameAnalyticsWithIndexStatus;
|
||||
}
|
||||
|
||||
export interface JobsExistsResponse {
|
||||
|
@ -152,11 +152,11 @@ export const dataFrameAnalyticsApiProvider = (httpService: HttpService) => ({
|
|||
deleteDataFrameAnalyticsAndDestIndex(
|
||||
analyticsId: string,
|
||||
deleteDestIndex: boolean,
|
||||
deleteDestIndexPattern: boolean
|
||||
deleteDestDataView: boolean
|
||||
) {
|
||||
return httpService.http<DeleteDataFrameAnalyticsWithIndexResponse>({
|
||||
path: `${ML_INTERNAL_BASE_PATH}/data_frame/analytics/${analyticsId}`,
|
||||
query: { deleteDestIndex, deleteDestIndexPattern },
|
||||
query: { deleteDestIndex, deleteDestDataView },
|
||||
method: 'DELETE',
|
||||
version: '1',
|
||||
});
|
||||
|
|
|
@ -129,6 +129,6 @@ export function timeBasedIndexCheck(dataView: DataView, showNotification = false
|
|||
* Returns true if the data view index pattern contains a :
|
||||
* which means it is cross-cluster
|
||||
*/
|
||||
export function isCcsIndexPattern(dataViewIndexPattern: string) {
|
||||
return dataViewIndexPattern.includes(':');
|
||||
export function isCcsIndexPattern(indexPattern: string) {
|
||||
return indexPattern.includes(':');
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { DataViewsService } from '@kbn/data-views-plugin/common';
|
|||
|
||||
export class DataViewHandler {
|
||||
constructor(private dataViewService: DataViewsService) {}
|
||||
// returns a id based on an index pattern name
|
||||
// returns a id based on an data view name
|
||||
async getDataViewId(indexName: string) {
|
||||
const dv = (await this.dataViewService.find(indexName)).find(
|
||||
({ title }) => title === indexName
|
|
@ -18,35 +18,35 @@ import { wrapError } from '../client/error_wrapper';
|
|||
import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages';
|
||||
import type { RouteInitialization } from '../types';
|
||||
import {
|
||||
dataAnalyticsJobConfigSchema,
|
||||
dataAnalyticsJobUpdateSchema,
|
||||
dataAnalyticsEvaluateSchema,
|
||||
dataAnalyticsExplainSchema,
|
||||
analyticsIdSchema,
|
||||
analyticsMapQuerySchema,
|
||||
dataFrameAnalyticsJobConfigSchema,
|
||||
dataFrameAnalyticsJobUpdateSchema,
|
||||
dataFrameAnalyticsEvaluateSchema,
|
||||
dataFrameAnalyticsExplainSchema,
|
||||
dataFrameAnalyticsIdSchema,
|
||||
dataFrameAnalyticsMapQuerySchema,
|
||||
stopsDataFrameAnalyticsJobQuerySchema,
|
||||
deleteDataFrameAnalyticsJobSchema,
|
||||
jobsExistSchema,
|
||||
analyticsQuerySchema,
|
||||
analyticsNewJobCapsParamsSchema,
|
||||
analyticsNewJobCapsQuerySchema,
|
||||
} from './schemas/data_analytics_schema';
|
||||
dataFrameAnalyticsJobsExistSchema,
|
||||
dataFrameAnalyticsQuerySchema,
|
||||
dataFrameAnalyticsNewJobCapsParamsSchema,
|
||||
dataFrameAnalyticsNewJobCapsQuerySchema,
|
||||
} from './schemas/data_frame_analytics_schema';
|
||||
import type { ExtendAnalyticsMapArgs } from '../models/data_frame_analytics/types';
|
||||
import { DataViewHandler } from '../models/data_frame_analytics/index_patterns';
|
||||
import { DataViewHandler } from '../models/data_frame_analytics/data_view_handler';
|
||||
import { AnalyticsManager } from '../models/data_frame_analytics/analytics_manager';
|
||||
import { validateAnalyticsJob } from '../models/data_frame_analytics/validation';
|
||||
import { fieldServiceProvider } from '../models/job_service/new_job_caps/field_service';
|
||||
import { getAuthorizationHeader } from '../lib/request_authorization';
|
||||
import type { MlClient } from '../lib/ml_client';
|
||||
|
||||
function getDataViewId(dataViewsService: DataViewsService, patternName: string) {
|
||||
async function getDataViewId(dataViewsService: DataViewsService, patternName: string) {
|
||||
const iph = new DataViewHandler(dataViewsService);
|
||||
return iph.getDataViewId(patternName);
|
||||
return await iph.getDataViewId(patternName);
|
||||
}
|
||||
|
||||
function deleteDestDataViewById(dataViewsService: DataViewsService, dataViewId: string) {
|
||||
async function deleteDestDataViewById(dataViewsService: DataViewsService, dataViewId: string) {
|
||||
const iph = new DataViewHandler(dataViewsService);
|
||||
return iph.deleteDataViewById(dataViewId);
|
||||
return await iph.deleteDataViewById(dataViewId);
|
||||
}
|
||||
|
||||
function getExtendedMap(
|
||||
|
@ -144,7 +144,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
query: analyticsQuerySchema,
|
||||
query: dataFrameAnalyticsQuerySchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -185,8 +185,8 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
query: analyticsQuerySchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
query: dataFrameAnalyticsQuerySchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -262,7 +262,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -305,8 +305,8 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
body: dataAnalyticsJobConfigSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
body: dataFrameAnalyticsJobConfigSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -352,7 +352,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
body: dataAnalyticsEvaluateSchema,
|
||||
body: dataFrameAnalyticsEvaluateSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -397,7 +397,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
body: dataAnalyticsExplainSchema,
|
||||
body: dataFrameAnalyticsExplainSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -440,7 +440,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
query: deleteDataFrameAnalyticsJobSchema,
|
||||
},
|
||||
},
|
||||
|
@ -449,11 +449,11 @@ export function dataFrameAnalyticsRoutes(
|
|||
async ({ mlClient, client, request, response, getDataViewsService }) => {
|
||||
try {
|
||||
const { analyticsId } = request.params;
|
||||
const { deleteDestIndex, deleteDestIndexPattern } = request.query;
|
||||
const { deleteDestIndex, deleteDestDataView } = request.query;
|
||||
let destinationIndex: string | undefined;
|
||||
const analyticsJobDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false };
|
||||
const destIndexDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false };
|
||||
const destIndexPatternDeleted: DeleteDataFrameAnalyticsWithIndexStatus = {
|
||||
const destDataViewDeleted: DeleteDataFrameAnalyticsWithIndexStatus = {
|
||||
success: false,
|
||||
};
|
||||
|
||||
|
@ -473,7 +473,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
return response.customError(wrapError(e));
|
||||
}
|
||||
|
||||
if (deleteDestIndex || deleteDestIndexPattern) {
|
||||
if (deleteDestIndex || deleteDestDataView) {
|
||||
// If user checks box to delete the destinationIndex associated with the job
|
||||
if (destinationIndex && deleteDestIndex) {
|
||||
// Verify if user has privilege to delete the destination index
|
||||
|
@ -494,16 +494,16 @@ export function dataFrameAnalyticsRoutes(
|
|||
}
|
||||
|
||||
// Delete the index pattern if there's an index pattern that matches the name of dest index
|
||||
if (destinationIndex && deleteDestIndexPattern) {
|
||||
if (destinationIndex && deleteDestDataView) {
|
||||
try {
|
||||
const dataViewsService = await getDataViewsService();
|
||||
const dataViewId = await getDataViewId(dataViewsService, destinationIndex);
|
||||
if (dataViewId) {
|
||||
await deleteDestDataViewById(dataViewsService, dataViewId);
|
||||
}
|
||||
destIndexPatternDeleted.success = true;
|
||||
destDataViewDeleted.success = true;
|
||||
} catch (deleteDestIndexPatternError) {
|
||||
destIndexPatternDeleted.error = deleteDestIndexPatternError;
|
||||
destDataViewDeleted.error = deleteDestIndexPatternError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
const results = {
|
||||
analyticsJobDeleted,
|
||||
destIndexDeleted,
|
||||
destIndexPatternDeleted,
|
||||
destDataViewDeleted,
|
||||
};
|
||||
return response.ok({
|
||||
body: results,
|
||||
|
@ -555,7 +555,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -597,7 +597,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
query: stopsDataFrameAnalyticsJobQuerySchema,
|
||||
},
|
||||
},
|
||||
|
@ -640,8 +640,8 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
body: dataAnalyticsJobUpdateSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
body: dataFrameAnalyticsJobUpdateSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -686,7 +686,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -728,7 +728,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
body: jobsExistSchema,
|
||||
body: dataFrameAnalyticsJobsExistSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -785,8 +785,8 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsIdSchema,
|
||||
query: analyticsMapQuerySchema,
|
||||
params: dataFrameAnalyticsIdSchema,
|
||||
query: dataFrameAnalyticsMapQuerySchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -851,8 +851,8 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
params: analyticsNewJobCapsParamsSchema,
|
||||
query: analyticsNewJobCapsQuerySchema,
|
||||
params: dataFrameAnalyticsNewJobCapsParamsSchema,
|
||||
query: dataFrameAnalyticsNewJobCapsQuerySchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -906,7 +906,7 @@ export function dataFrameAnalyticsRoutes(
|
|||
version: '1',
|
||||
validate: {
|
||||
request: {
|
||||
body: dataAnalyticsJobConfigSchema,
|
||||
body: dataFrameAnalyticsJobConfigSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { schema } from '@kbn/config-schema';
|
||||
import { runtimeMappingsSchema } from './runtime_mappings_schema';
|
||||
|
||||
export const dataAnalyticsJobConfigSchema = schema.object({
|
||||
export const dataFrameAnalyticsJobConfigSchema = schema.object({
|
||||
description: schema.maybe(schema.string()),
|
||||
_meta: schema.maybe(schema.object({}, { unknowns: 'allow' })),
|
||||
dest: schema.object({
|
||||
|
@ -35,7 +35,7 @@ export const dataAnalyticsJobConfigSchema = schema.object({
|
|||
max_num_threads: schema.maybe(schema.number()),
|
||||
});
|
||||
|
||||
export const dataAnalyticsEvaluateSchema = schema.object({
|
||||
export const dataFrameAnalyticsEvaluateSchema = schema.object({
|
||||
index: schema.string(),
|
||||
query: schema.maybe(schema.any()),
|
||||
evaluation: schema.maybe(
|
||||
|
@ -47,7 +47,7 @@ export const dataAnalyticsEvaluateSchema = schema.object({
|
|||
),
|
||||
});
|
||||
|
||||
export const dataAnalyticsExplainSchema = schema.object({
|
||||
export const dataFrameAnalyticsExplainSchema = schema.object({
|
||||
description: schema.maybe(schema.string()),
|
||||
dest: schema.maybe(schema.any()),
|
||||
/** Source */
|
||||
|
@ -63,14 +63,14 @@ export const dataAnalyticsExplainSchema = schema.object({
|
|||
_meta: schema.maybe(schema.object({}, { unknowns: 'allow' })),
|
||||
});
|
||||
|
||||
export const analyticsIdSchema = schema.object({
|
||||
export const dataFrameAnalyticsIdSchema = schema.object({
|
||||
/**
|
||||
* Analytics ID
|
||||
*/
|
||||
analyticsId: schema.string(),
|
||||
});
|
||||
|
||||
export const analyticsQuerySchema = schema.object({
|
||||
export const dataFrameAnalyticsQuerySchema = schema.object({
|
||||
/**
|
||||
* Analytics Query
|
||||
*/
|
||||
|
@ -83,10 +83,10 @@ export const deleteDataFrameAnalyticsJobSchema = schema.object({
|
|||
* Analytics Destination Index
|
||||
*/
|
||||
deleteDestIndex: schema.maybe(schema.boolean()),
|
||||
deleteDestIndexPattern: schema.maybe(schema.boolean()),
|
||||
deleteDestDataView: schema.maybe(schema.boolean()),
|
||||
});
|
||||
|
||||
export const dataAnalyticsJobUpdateSchema = schema.object({
|
||||
export const dataFrameAnalyticsJobUpdateSchema = schema.object({
|
||||
description: schema.maybe(schema.string()),
|
||||
model_memory_limit: schema.maybe(schema.string()),
|
||||
allow_lazy_start: schema.maybe(schema.boolean()),
|
||||
|
@ -98,17 +98,19 @@ export const stopsDataFrameAnalyticsJobQuerySchema = schema.object({
|
|||
force: schema.maybe(schema.boolean()),
|
||||
});
|
||||
|
||||
export const jobsExistSchema = schema.object({
|
||||
export const dataFrameAnalyticsJobsExistSchema = schema.object({
|
||||
analyticsIds: schema.arrayOf(schema.string()),
|
||||
allSpaces: schema.maybe(schema.boolean()),
|
||||
});
|
||||
|
||||
export const analyticsMapQuerySchema = schema.maybe(
|
||||
export const dataFrameAnalyticsMapQuerySchema = schema.maybe(
|
||||
schema.object({ treatAsRoot: schema.maybe(schema.any()), type: schema.maybe(schema.string()) })
|
||||
);
|
||||
|
||||
export const analyticsNewJobCapsParamsSchema = schema.object({ indexPattern: schema.string() });
|
||||
export const dataFrameAnalyticsNewJobCapsParamsSchema = schema.object({
|
||||
indexPattern: schema.string(),
|
||||
});
|
||||
|
||||
export const analyticsNewJobCapsQuerySchema = schema.maybe(
|
||||
export const dataFrameAnalyticsNewJobCapsQuerySchema = schema.maybe(
|
||||
schema.object({ rollup: schema.maybe(schema.string()) })
|
||||
);
|
|
@ -17,7 +17,7 @@ import {
|
|||
getFieldType,
|
||||
getDataGridSchemaFromKibanaFieldType,
|
||||
getDataGridSchemaFromESFieldType,
|
||||
getFieldsFromKibanaIndexPattern,
|
||||
getFieldsFromKibanaDataView,
|
||||
showDataGridColumnChartErrorMessageToast,
|
||||
useDataGrid,
|
||||
useRenderCellValue,
|
||||
|
@ -140,7 +140,7 @@ export const useIndexData = (
|
|||
allPopulatedFields = [...new Set(docs.map(Object.keys).flat(1))];
|
||||
}
|
||||
|
||||
const allDataViewFields = getFieldsFromKibanaIndexPattern(dataView);
|
||||
const allDataViewFields = getFieldsFromKibanaDataView(dataView);
|
||||
return allPopulatedFields.filter((d) => allDataViewFields.includes(d)).sort();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dataViewFieldsData, populatedFields]);
|
||||
|
|
|
@ -25329,7 +25329,7 @@
|
|||
"xpack.ml.dataFrame.analytics.create.searchSelection.CcsErrorCallOutTitle": "Les vues de données utilisant la recherche inter-clusters ne sont pas prises en charge.",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.errorGettingDataViewTitle": "Erreur lors du chargement de la vue de données utilisée par la recherche enregistrée",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.notFoundLabel": "Aucun recherche enregistrée ni aucun index correspondants n'ont été trouvés.",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.indexPattern": "Vue de données",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.dataView": "Vue de données",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.search": "Recherche enregistrée",
|
||||
"xpack.ml.dataframe.analytics.create.shouldCreateDataViewMessage": "Vous ne pourrez peut-être pas visualiser les résultats de la tâche si aucune vue de données n'est créée pour l'index de destination.",
|
||||
"xpack.ml.dataframe.analytics.create.softTreeDepthLimitInputAriaLabel": "Les arbres de décision dépassant cette profondeur sont pénalisés dans les calculs de perte.",
|
||||
|
|
|
@ -25328,7 +25328,7 @@
|
|||
"xpack.ml.dataFrame.analytics.create.searchSelection.CcsErrorCallOutTitle": "クラスター横断検索を使用するデータビューはサポートされていません。",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.errorGettingDataViewTitle": "保存された検索で使用されているデータビューの読み込みエラー",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.notFoundLabel": "一致インデックスまたは保存した検索が見つかりません。",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.indexPattern": "データビュー",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.dataView": "データビュー",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.search": "保存検索",
|
||||
"xpack.ml.dataframe.analytics.create.shouldCreateDataViewMessage": "デスティネーションインデックスのデータビューが作成されていない場合は、ジョブ結果を表示できないことがあります。",
|
||||
"xpack.ml.dataframe.analytics.create.softTreeDepthLimitInputAriaLabel": "この深さを超える決定木は、損失計算でペナルティがあります。",
|
||||
|
|
|
@ -25327,7 +25327,7 @@
|
|||
"xpack.ml.dataFrame.analytics.create.searchSelection.CcsErrorCallOutTitle": "不支持使用跨集群搜索的数据视图。",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.errorGettingDataViewTitle": "加载已保存搜索所使用的数据视图时出错",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.notFoundLabel": "未找到匹配的索引或已保存搜索。",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.indexPattern": "数据视图",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.dataView": "数据视图",
|
||||
"xpack.ml.dataFrame.analytics.create.searchSelection.savedObjectType.search": "已保存搜索",
|
||||
"xpack.ml.dataframe.analytics.create.shouldCreateDataViewMessage": "如果没有为目标索引创建数据视图,则可能无法查看作业结果。",
|
||||
"xpack.ml.dataframe.analytics.create.softTreeDepthLimitInputAriaLabel": "超过此深度的决策树将在损失计算中被罚分。",
|
||||
|
|
|
@ -148,13 +148,13 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
|
||||
expect(body.analyticsJobDeleted.success).to.eql(true);
|
||||
expect(body.destIndexDeleted.success).to.eql(true);
|
||||
expect(body.destIndexPatternDeleted.success).to.eql(false);
|
||||
expect(body.destDataViewDeleted.success).to.eql(false);
|
||||
await ml.api.waitForDataFrameAnalyticsJobNotToExist(analyticsId);
|
||||
await ml.api.assertIndicesNotToExist(destinationIndex);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with deleteDestIndexPattern setting', function () {
|
||||
describe('with deleteDestDataView setting', function () {
|
||||
const analyticsId = `${jobId}_3`;
|
||||
const destinationIndex = generateDestinationIndex(analyticsId);
|
||||
|
||||
|
@ -170,20 +170,20 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
it('should delete job and data view by id', async () => {
|
||||
const { body, status } = await supertest
|
||||
.delete(`/internal/ml/data_frame/analytics/${analyticsId}`)
|
||||
.query({ deleteDestIndexPattern: true })
|
||||
.query({ deleteDestDataView: true })
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(getCommonRequestHeader('1'));
|
||||
ml.api.assertResponseStatusCode(200, status, body);
|
||||
|
||||
expect(body.analyticsJobDeleted.success).to.eql(true);
|
||||
expect(body.destIndexDeleted.success).to.eql(false);
|
||||
expect(body.destIndexPatternDeleted.success).to.eql(true);
|
||||
expect(body.destDataViewDeleted.success).to.eql(true);
|
||||
await ml.api.waitForDataFrameAnalyticsJobNotToExist(analyticsId);
|
||||
await ml.testResources.assertDataViewNotExist(destinationIndex);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with deleteDestIndex & deleteDestIndexPattern setting', function () {
|
||||
describe('with deleteDestIndex & deleteDestDataView setting', function () {
|
||||
const analyticsId = `${jobId}_4`;
|
||||
const destinationIndex = generateDestinationIndex(analyticsId);
|
||||
|
||||
|
@ -202,14 +202,14 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
it('should delete job, target index, and data view by id', async () => {
|
||||
const { body, status } = await supertest
|
||||
.delete(`/internal/ml/data_frame/analytics/${analyticsId}`)
|
||||
.query({ deleteDestIndex: true, deleteDestIndexPattern: true })
|
||||
.query({ deleteDestIndex: true, deleteDestDataView: true })
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(getCommonRequestHeader('1'));
|
||||
ml.api.assertResponseStatusCode(200, status, body);
|
||||
|
||||
expect(body.analyticsJobDeleted.success).to.eql(true);
|
||||
expect(body.destIndexDeleted.success).to.eql(true);
|
||||
expect(body.destIndexPatternDeleted.success).to.eql(true);
|
||||
expect(body.destDataViewDeleted.success).to.eql(true);
|
||||
await ml.api.waitForDataFrameAnalyticsJobNotToExist(analyticsId);
|
||||
await ml.api.assertIndicesNotToExist(destinationIndex);
|
||||
await ml.testResources.assertDataViewNotExist(destinationIndex);
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
|
||||
const testDiscoverCustomUrl: DiscoverUrlConfig = {
|
||||
label: 'Show data',
|
||||
indexPattern: 'ft_bank_marketing',
|
||||
indexName: 'ft_bank_marketing',
|
||||
queryEntityFieldNames: ['day'],
|
||||
timeRange: TIME_RANGE_TYPE.AUTO,
|
||||
};
|
||||
|
@ -76,7 +76,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'y',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '60mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
fieldStatsEntries: [
|
||||
{
|
||||
fieldName: 'age',
|
||||
|
@ -339,9 +339,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
await ml.testExecution.logTestStep('sets the create data view switch');
|
||||
await ml.dataFrameAnalyticsCreation.assertCreateDataViewSwitchExists();
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(
|
||||
testData.createIndexPattern
|
||||
);
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(testData.createDataView);
|
||||
});
|
||||
|
||||
it('runs the analytics job and displays it correctly in the job list', async () => {
|
||||
|
|
|
@ -19,7 +19,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const testDataList: Array<{
|
||||
suiteTitle: string;
|
||||
archive: string;
|
||||
indexPattern: { name: string; timeField: string };
|
||||
dataView: { name: string; timeField: string };
|
||||
job: DeepPartial<DataFrameAnalyticsConfig>;
|
||||
}> = (() => {
|
||||
const timestamp = Date.now();
|
||||
|
@ -28,7 +28,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'classification job supported by the form',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/bm_classification',
|
||||
indexPattern: { name: 'ft_bank_marketing', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_bank_marketing', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `bm_1_${timestamp}`,
|
||||
description:
|
||||
|
@ -63,7 +63,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'outlier detection job supported by the form',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/ihp_outlier',
|
||||
indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `ihp_1_${timestamp}`,
|
||||
description: 'This is the job description',
|
||||
|
@ -92,7 +92,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'regression job supported by the form',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/egs_regression',
|
||||
indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_egs_regression', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `egs_1_${timestamp}`,
|
||||
description: 'This is the job description',
|
||||
|
@ -142,8 +142,8 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
before(async () => {
|
||||
await esArchiver.loadIfNeeded(testData.archive);
|
||||
await ml.testResources.createDataViewIfNeeded(
|
||||
testData.indexPattern.name,
|
||||
testData.indexPattern.timeField
|
||||
testData.dataView.name,
|
||||
testData.dataView.timeField
|
||||
);
|
||||
await ml.api.createDataFrameAnalyticsJob(testData.job as DataFrameAnalyticsConfig);
|
||||
|
||||
|
@ -159,7 +159,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
await ml.api.deleteIndices(testData.job.dest!.index as string);
|
||||
await ml.testResources.deleteDataViewByTitle(testData.job.dest!.index as string);
|
||||
await ml.testResources.deleteDataViewByTitle(cloneDestIndex);
|
||||
await ml.testResources.deleteDataViewByTitle(testData.indexPattern.name);
|
||||
await ml.testResources.deleteDataViewByTitle(testData.dataView.name);
|
||||
});
|
||||
|
||||
it('opens the existing job in the data frame analytics job wizard', async () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
|
||||
const testDiscoverCustomUrl: DiscoverUrlConfig = {
|
||||
label: 'Show data',
|
||||
indexPattern: 'ft_farequote',
|
||||
indexName: 'ft_farequote',
|
||||
queryEntityFieldNames: ['airline'],
|
||||
timeRange: TIME_RANGE_TYPE.AUTO,
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
|
||||
const testDiscoverCustomUrl: DiscoverUrlConfig = {
|
||||
label: 'Show data',
|
||||
indexPattern: 'ft_ihp_outlier',
|
||||
indexName: 'ft_ihp_outlier',
|
||||
queryEntityFieldNames: ['SaleType'],
|
||||
timeRange: TIME_RANGE_TYPE.AUTO,
|
||||
};
|
||||
|
@ -83,7 +83,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
modelMemory: '5mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
advancedEditorContent: [
|
||||
'{',
|
||||
' "description": "Outlier detection job based on ft_ihp_outlier dataset with runtime fields",',
|
||||
|
@ -325,9 +325,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
await ml.testExecution.logTestStep('sets the create data view switch');
|
||||
await ml.dataFrameAnalyticsCreation.assertCreateDataViewSwitchExists();
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(
|
||||
testData.createIndexPattern
|
||||
);
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(testData.createDataView);
|
||||
});
|
||||
|
||||
it('runs the analytics job and displays it correctly in the job list', async () => {
|
||||
|
|
|
@ -63,7 +63,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
modelMemory: '1mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
histogramCharts: [
|
||||
|
@ -140,7 +140,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
modelMemory: '65mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
histogramCharts: [
|
||||
|
@ -217,7 +217,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
modelMemory: '65mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
histogramCharts: [
|
||||
|
@ -295,7 +295,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
modelMemory: '65mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
histogramCharts: [
|
||||
|
@ -464,9 +464,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
await ml.testExecution.logTestStep('sets the create data view switch');
|
||||
await ml.dataFrameAnalyticsCreation.assertCreateDataViewSwitchExists();
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(
|
||||
testData.createIndexPattern
|
||||
);
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(testData.createDataView);
|
||||
});
|
||||
|
||||
it('runs the analytics job and displays it correctly in the job list', async () => {
|
||||
|
|
|
@ -36,7 +36,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
const testDiscoverCustomUrl: DiscoverUrlConfig = {
|
||||
label: 'Show data',
|
||||
indexPattern: 'ft_egs_regression',
|
||||
indexName: 'ft_egs_regression',
|
||||
queryEntityFieldNames: ['stabf'],
|
||||
timeRange: TIME_RANGE_TYPE.AUTO,
|
||||
};
|
||||
|
@ -90,7 +90,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'stab',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '20mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
advancedEditorContent: [
|
||||
'{',
|
||||
' "description": "Regression job based on ft_egs_regression dataset with runtime fields",',
|
||||
|
@ -340,9 +340,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
await ml.testExecution.logTestStep('sets the create data view switch');
|
||||
await ml.dataFrameAnalyticsCreation.assertCreateDataViewSwitchExists();
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(
|
||||
testData.createIndexPattern
|
||||
);
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(testData.createDataView);
|
||||
});
|
||||
|
||||
it('runs the analytics job and displays it correctly in the job list', async () => {
|
||||
|
|
|
@ -73,7 +73,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'responsetime',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '20mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
runtimeFieldsEditorContent: ['{', ' "uppercase_airline": {', ' "type": "keyword",'],
|
||||
|
@ -161,7 +161,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'responsetime',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '20mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
runtimeFieldsEditorContent: ['{', ' "uppercase_airline": {', ' "type": "keyword",'],
|
||||
|
@ -249,7 +249,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'responsetime',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '20mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
runtimeFieldsEditorContent: ['{', ' "uppercase_airline": {', ' "type": "keyword",'],
|
||||
|
@ -331,7 +331,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
dependentVariable: 'responsetime',
|
||||
trainingPercent: 20,
|
||||
modelMemory: '20mb',
|
||||
createIndexPattern: true,
|
||||
createDataView: true,
|
||||
expected: {
|
||||
source: 'ft_farequote_small',
|
||||
runtimeFieldsEditorContent: ['{', ' "uppercase_airline": {', ' "type": "keyword",'],
|
||||
|
@ -499,9 +499,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
await ml.testExecution.logTestStep('sets the create data view switch');
|
||||
await ml.dataFrameAnalyticsCreation.assertCreateDataViewSwitchExists();
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(
|
||||
testData.createIndexPattern
|
||||
);
|
||||
await ml.dataFrameAnalyticsCreation.setCreateDataViewSwitchState(testData.createDataView);
|
||||
});
|
||||
|
||||
it('runs the analytics job and displays it correctly in the job list', async () => {
|
||||
|
|
|
@ -18,7 +18,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const testDataList: Array<{
|
||||
suiteTitle: string;
|
||||
archive: string;
|
||||
indexPattern: { name: string; timeField: string };
|
||||
dataView: { name: string; timeField: string };
|
||||
job: DeepPartial<DataFrameAnalyticsConfig>;
|
||||
sortBy: {
|
||||
column: string;
|
||||
|
@ -38,7 +38,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'binary classification job',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/ihp_outlier',
|
||||
indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `ihp_fi_binary_${timestamp}`,
|
||||
description:
|
||||
|
@ -107,7 +107,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'multi class classification job',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/ihp_outlier',
|
||||
indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `ihp_fi_multi_${timestamp}`,
|
||||
description:
|
||||
|
@ -178,7 +178,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
suiteTitle: 'regression job',
|
||||
archive: 'x-pack/test/functional/es_archives/ml/egs_regression',
|
||||
indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' },
|
||||
dataView: { name: 'ft_egs_regression', timeField: '@timestamp' },
|
||||
job: {
|
||||
id: `egs_fi_reg_${timestamp}`,
|
||||
description: 'This is the job description',
|
||||
|
@ -253,8 +253,8 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
for (const testData of testDataList) {
|
||||
await esArchiver.loadIfNeeded(testData.archive);
|
||||
await ml.testResources.createDataViewIfNeeded(
|
||||
testData.indexPattern.name,
|
||||
testData.indexPattern.timeField
|
||||
testData.dataView.name,
|
||||
testData.dataView.timeField
|
||||
);
|
||||
await ml.api.createAndRunDFAJob(testData.job as DataFrameAnalyticsConfig);
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
after(async () => {
|
||||
await ml.api.cleanMlIndices();
|
||||
for (const testData of testDataList) {
|
||||
await ml.testResources.deleteDataViewByTitle(testData.indexPattern.name);
|
||||
await ml.testResources.deleteDataViewByTitle(testData.dataView.name);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { MlCustomUrls } from './custom_urls';
|
|||
|
||||
export interface DiscoverUrlConfig {
|
||||
label: string;
|
||||
indexPattern: string;
|
||||
indexName: string;
|
||||
queryEntityFieldNames: string[];
|
||||
timeRange: TimeRangeType;
|
||||
timeRangeInterval?: string;
|
||||
|
@ -98,7 +98,7 @@ export function MachineLearningDataFrameAnalyticsEditProvider(
|
|||
);
|
||||
await mlCommonUI.selectSelectValueByVisibleText(
|
||||
'mlJobCustomUrlDiscoverIndexPatternInput',
|
||||
customUrl.indexPattern
|
||||
customUrl.indexName
|
||||
);
|
||||
await customUrls.setCustomUrlQueryEntityFieldNames(customUrl.queryEntityFieldNames);
|
||||
if (addTimerange) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue