Skip to content

Commit

Permalink
ensure field options update on dataView change for DFA
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarezmelissa87 committed Apr 17, 2023
1 parent b689c27 commit 6740df3
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { ChangeEvent, FC } from 'react';
import React, { ChangeEvent, useState, useEffect, FC } from 'react';

import {
EuiComboBox,
Expand All @@ -25,11 +25,19 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { DataViewListItem } from '@kbn/data-views-plugin/common';
import { DataView } from '@kbn/data-views-plugin/public';
import { CustomUrlSettings, isValidCustomUrlSettingsTimeRange } from './utils';
import { isValidLabel } from '../../../util/custom_url_utils';
import {
isDataFrameAnalyticsConfigs,
type DataFrameAnalyticsConfig,
} from '../../../../../common/types/data_frame_analytics';
import { Job, isAnomalyDetectionJob } from '../../../../../common/types/anomaly_detection_jobs';

import { TIME_RANGE_TYPE, TimeRangeType, URL_TYPE } from './constants';
import { UrlConfig } from '../../../../../common/types/custom_urls';
import { getQueryEntityFieldNames, getSupportedFieldNames } from './utils';
import { useMlKibana } from '../../../contexts/kibana';

function getLinkToOptions() {
return [
Expand All @@ -54,14 +62,24 @@ function getLinkToOptions() {
];
}

function getDropDownOptions(job: Job | DataFrameAnalyticsConfig, dataView?: DataView) {
if (isAnomalyDetectionJob(job)) {
return getQueryEntityFieldNames(job);
} else if (isDataFrameAnalyticsConfigs(job) && dataView !== undefined) {
return getSupportedFieldNames(job, dataView);
}
return [];
}

interface CustomUrlEditorProps {
customUrl: CustomUrlSettings | undefined;
setEditCustomUrl: (url: CustomUrlSettings) => void;
savedCustomUrls: UrlConfig[];
dashboards: Array<{ id: string; title: string }>;
dataViewListItems: DataViewListItem[];
queryEntityFieldNames: string[];
showTimeRangeSelector?: boolean;
// dataView?: DataView;
job: Job | DataFrameAnalyticsConfig;
}

/*
Expand All @@ -73,9 +91,38 @@ export const CustomUrlEditor: FC<CustomUrlEditorProps> = ({
savedCustomUrls,
dashboards,
dataViewListItems,
queryEntityFieldNames,
showTimeRangeSelector = true,
job,
// dataView,
}) => {
const [queryEntityFieldNames, setQueryEntityFieldNames] = useState<string[]>([]);
const isAnomalyJob = isAnomalyDetectionJob(job);

const {
services: {
data: { dataViews },
},
} = useMlKibana();

useEffect(() => {
// For DFA uses the destination index Data View to get the query entities and falls back to source index Data View.
async function getQueryEntityDropdownOptions() {
let dataViewToUse: DataView | undefined;
const dataViewId = customUrl?.kibanaSettings?.discoverIndexPatternId;

try {
dataViewToUse = await dataViews.get(dataViewId ?? '');
} catch (e) {
dataViewToUse = undefined;
}
const dropDownOptions = await getDropDownOptions(job, dataViewToUse);
setQueryEntityFieldNames(dropDownOptions);
}

if (job !== undefined) {
getQueryEntityDropdownOptions();
}
}, [dataViews, job, customUrl?.kibanaSettings?.discoverIndexPatternId]);

if (customUrl === undefined) {
return null;
}
Expand Down Expand Up @@ -307,58 +354,57 @@ export const CustomUrlEditor: FC<CustomUrlEditorProps> = ({
</EuiFormRow>
)}

{(type === URL_TYPE.KIBANA_DASHBOARD || type === URL_TYPE.KIBANA_DISCOVER) &&
showTimeRangeSelector && (
<>
<EuiSpacer size="m" />
<EuiFlexGroup>
<EuiFlexItem grow={false}>
{(type === URL_TYPE.KIBANA_DASHBOARD || type === URL_TYPE.KIBANA_DISCOVER) && isAnomalyJob && (
<>
<EuiSpacer size="m" />
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.ml.customUrlsEditor.timeRangeLabel"
defaultMessage="Time range"
/>
}
className="url-time-range"
display="rowCompressed"
>
<EuiSelect
options={timeRangeOptions}
value={timeRange.type}
onChange={onTimeRangeTypeChange}
data-test-subj="mlJobCustomUrlTimeRangeInput"
compressed
/>
</EuiFormRow>
</EuiFlexItem>
{timeRange.type === TIME_RANGE_TYPE.INTERVAL && (
<EuiFlexItem>
<EuiFormRow
label={
<FormattedMessage
id="xpack.ml.customUrlsEditor.timeRangeLabel"
defaultMessage="Time range"
id="xpack.ml.customUrlsEditor.intervalLabel"
defaultMessage="Interval"
/>
}
className="url-time-range"
error={invalidIntervalError}
isInvalid={isInvalidTimeRange}
display="rowCompressed"
>
<EuiSelect
options={timeRangeOptions}
value={timeRange.type}
onChange={onTimeRangeTypeChange}
data-test-subj="mlJobCustomUrlTimeRangeInput"
<EuiFieldText
value={timeRange.interval}
onChange={onTimeRangeIntervalChange}
isInvalid={isInvalidTimeRange}
data-test-subj="mlJobCustomUrlTimeRangeIntervalInput"
compressed
/>
</EuiFormRow>
</EuiFlexItem>
{timeRange.type === TIME_RANGE_TYPE.INTERVAL && (
<EuiFlexItem>
<EuiFormRow
label={
<FormattedMessage
id="xpack.ml.customUrlsEditor.intervalLabel"
defaultMessage="Interval"
/>
}
className="url-time-range"
error={invalidIntervalError}
isInvalid={isInvalidTimeRange}
display="rowCompressed"
>
<EuiFieldText
value={timeRange.interval}
onChange={onTimeRangeIntervalChange}
isInvalid={isInvalidTimeRange}
data-test-subj="mlJobCustomUrlTimeRangeIntervalInput"
compressed
/>
</EuiFormRow>
</EuiFlexItem>
)}
</EuiFlexGroup>
</>
)}
)}
</EuiFlexGroup>
</>
)}

{type === URL_TYPE.OTHER && (
<EuiFormRow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ export function getNewCustomUrlDefaults(
// which matches the indices configured in the job datafeed.
let query: estypes.QueryDslQueryContainer = {};
let indicesName: string | undefined;
let backupIndicesName: string | undefined;
let backupDataViewId: string | undefined;
let jobId;

if (
isAnomalyDetectionJob(job) &&
dataViews !== undefined &&
Expand All @@ -106,12 +109,16 @@ export function getNewCustomUrlDefaults(
jobId = job.job_id;
} else if (isDataFrameAnalyticsConfigs(job) && dataViews !== undefined && dataViews.length > 0) {
indicesName = job.dest.index;
backupIndicesName = job.source.index[0];
query = job.source?.query ?? {};
jobId = job.id;
}

const defaultDataViewId = dataViews.find((dv) => dv.title === indicesName)?.id;
kibanaSettings.discoverIndexPatternId = defaultDataViewId;
if (defaultDataViewId === undefined && backupIndicesName !== undefined) {
backupDataViewId = dataViews.find((dv) => dv.title === backupIndicesName)?.id;
}
kibanaSettings.discoverIndexPatternId = defaultDataViewId ?? backupDataViewId ?? '';
kibanaSettings.filters =
defaultDataViewId === null ? [] : getFiltersForDSLQuery(query, defaultDataViewId, jobId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
EuiModalFooter,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { DataView } from '@kbn/data-views-plugin/public';

import { i18n } from '@kbn/i18n';
import { withKibana } from '@kbn/kibana-react-plugin/public';
Expand All @@ -31,8 +30,6 @@ import { MlKibanaReactContextValue } from '../../contexts/kibana';
import { CustomUrlEditor, CustomUrlList } from './custom_url_editor';
import {
getNewCustomUrlDefaults,
getQueryEntityFieldNames,
getSupportedFieldNames,
isValidCustomUrlSettings,
buildCustomUrlFromSettings,
getTestUrl,
Expand All @@ -43,37 +40,21 @@ import {
loadDataViewListItems,
} from '../../jobs/jobs_list/components/edit_job_flyout/edit_utils';
import { openCustomUrlWindow } from '../../util/custom_url_utils';
import { Job, isAnomalyDetectionJob } from '../../../../common/types/anomaly_detection_jobs';
import { UrlConfig } from '../../../../common/types/custom_urls';
import type { CustomUrlsWrapperProps } from './custom_urls_wrapper';
import {
isDataFrameAnalyticsConfigs,
type DataFrameAnalyticsConfig,
} from '../../../../common/types/data_frame_analytics';

function getDropDownOptions(job: Job | DataFrameAnalyticsConfig, dataView?: DataView) {
if (isAnomalyDetectionJob(job)) {
return getQueryEntityFieldNames(job);
} else if (isDataFrameAnalyticsConfigs(job) && dataView !== undefined) {
return getSupportedFieldNames(job, dataView);
}
return [];
}

const MAX_NUMBER_DASHBOARDS = 1000;

interface CustomUrlsState {
customUrls: UrlConfig[];
dashboards: Array<{ id: string; title: string }>;
dataViewListItems: DataViewListItem[];
queryEntityFieldNames: string[];
editorOpen: boolean;
editorSettings?: CustomUrlSettings;
supportedFilterFields: string[];
}
interface CustomUrlsProps extends CustomUrlsWrapperProps {
kibana: MlKibanaReactContextValue;
dataView?: DataView;
currentTimeFilter?: EsQueryTimeRange;
}

Expand All @@ -85,7 +66,6 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
customUrls: [],
dashboards: [],
dataViewListItems: [],
queryEntityFieldNames: [],
editorOpen: false,
supportedFilterFields: [],
};
Expand All @@ -95,8 +75,6 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
return {
job: props.job,
customUrls: props.jobCustomUrls,
// For DFA uses the destination index Data View to get the query entities and falls back to source index Data View.
queryEntityFieldNames: getDropDownOptions(props.job, props.dataView),
};
}

Expand Down Expand Up @@ -223,25 +201,17 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
};

renderEditor() {
const {
customUrls,
editorOpen,
editorSettings,
dashboards,
dataViewListItems,
queryEntityFieldNames,
} = this.state;
const { customUrls, editorOpen, editorSettings, dashboards, dataViewListItems } = this.state;

const editMode = this.props.editMode ?? 'inline';
const editor = (
<CustomUrlEditor
showTimeRangeSelector={isAnomalyDetectionJob(this.props.job)}
customUrl={editorSettings}
setEditCustomUrl={this.setEditCustomUrl}
savedCustomUrls={customUrls}
dashboards={dashboards}
dataViewListItems={dataViewListItems}
queryEntityFieldNames={queryEntityFieldNames}
job={this.props.job}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
* 2.0.
*/

import React, { useEffect, useState, FC } from 'react';
import { DataView } from '@kbn/data-views-plugin/public';
import React, { FC } from 'react';
import { useMlKibana } from '../../contexts/kibana';
import { Job } from '../../../../common/types/anomaly_detection_jobs';
import { UrlConfig } from '../../../../common/types/custom_urls';
import { getDataViewIdFromName } from '../../util/index_utils';
import {
isDataFrameAnalyticsConfigs,
type DataFrameAnalyticsConfig,
} from '../../../../common/types/data_frame_analytics';
import { type DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_analytics';
import { CustomUrls } from './custom_urls';

export interface CustomUrlsWrapperProps {
Expand All @@ -25,53 +20,15 @@ export interface CustomUrlsWrapperProps {
}

export const CustomUrlsWrapper: FC<CustomUrlsWrapperProps> = (props) => {
const [dataView, setDataView] = useState<DataView | undefined>();

const {
services: {
data: {
dataViews,
query: {
timefilter: { timefilter },
},
},
},
} = useMlKibana();

useEffect(() => {
let active = true;

async function loadDataView() {
if (isDataFrameAnalyticsConfigs(props.job)) {
const destIndex = props.job.dest.index;
const sourceIndex = props.job.source.index[0];
let dataViewIdSource: string | null;
let dataViewIdDest: string | null;
let dv: DataView | undefined;

try {
dataViewIdSource = await getDataViewIdFromName(sourceIndex);
dataViewIdDest = await getDataViewIdFromName(destIndex);
dv = await dataViews.get(dataViewIdDest ?? dataViewIdSource ?? '');

if (dv === undefined) {
dv = await dataViews.get(dataViewIdSource ?? '');
}
if (!active) return;
setDataView(dv);
} catch (e) {
dv = undefined;
}

return dv;
}
}

loadDataView();
return () => {
active = false;
};
}, [dataViews, props.job]);

return <CustomUrls {...props} dataView={dataView} currentTimeFilter={timefilter.getTime()} />;
return <CustomUrls {...props} currentTimeFilter={timefilter.getTime()} />;
};

0 comments on commit 6740df3

Please sign in to comment.