Skip to content

Commit 819cf7d

Browse files
committed
[ML] Refactor to improve code structure for expandable section.
1 parent 7cc2ead commit 819cf7d

3 files changed

Lines changed: 176 additions & 126 deletions

File tree

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,36 @@ import './expandable_section.scss';
88

99
import React, { useState, FC, ReactNode } from 'react';
1010

11-
import { EuiButtonEmpty, EuiPanel } from '@elastic/eui';
11+
import {
12+
EuiBadge,
13+
EuiButtonEmpty,
14+
EuiFlexGroup,
15+
EuiFlexItem,
16+
EuiLoadingContent,
17+
EuiPanel,
18+
EuiText,
19+
} from '@elastic/eui';
1220

13-
interface ExpandableSectionProps {
21+
interface HeaderItem {
22+
// id is used as the React key and to construct a data-test-subj
23+
id: string;
24+
label?: ReactNode;
25+
value: ReactNode;
26+
}
27+
28+
const isHeaderItems = (arg: any): arg is HeaderItem[] => {
29+
return Array.isArray(arg);
30+
};
31+
32+
export interface ExpandableSectionProps {
1433
content: ReactNode;
15-
headerContent: ReactNode;
34+
headerItems?: HeaderItem[] | 'loading';
1635
isExpanded?: boolean;
1736
title: ReactNode;
1837
}
1938

2039
export const ExpandableSection: FC<ExpandableSectionProps> = ({
21-
headerContent,
40+
headerItems,
2241
// For now we don't have a need for complete external control
2342
// and just want to pass in a default value. If we wanted
2443
// full external control we'd also need to add a onToggleExpanded()
@@ -44,7 +63,24 @@ export const ExpandableSection: FC<ExpandableSectionProps> = ({
4463
>
4564
{title}
4665
</EuiButtonEmpty>
47-
{headerContent}
66+
{headerItems === 'loading' && <EuiLoadingContent lines={1} />}
67+
{isHeaderItems(headerItems) && (
68+
<EuiFlexGroup>
69+
{headerItems.map(({ label, value, id }) => (
70+
<EuiFlexItem grow={false} key={id}>
71+
{label !== undefined && value !== undefined && (
72+
<>
73+
<EuiText size="xs" color="subdued">
74+
<p>{label}</p>
75+
</EuiText>
76+
<EuiBadge>{value}</EuiBadge>
77+
</>
78+
)}
79+
{label === undefined && value}
80+
</EuiFlexItem>
81+
))}
82+
</EuiFlexGroup>
83+
)}
4884
</div>
4985
{isExpanded && content}
5086
</EuiPanel>

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
export { ExpandableSection } from './expandable_section';
7+
export { ExpandableSection, ExpandableSectionProps } from './expandable_section';

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx

Lines changed: 134 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ import { i18n } from '@kbn/i18n';
1010
import { FormattedMessage } from '@kbn/i18n/react';
1111

1212
import {
13-
EuiBadge,
14-
EuiFlexGroup,
15-
EuiFlexItem,
13+
EuiDataGridColumn,
1614
EuiHorizontalRule,
17-
EuiLoadingContent,
1815
EuiLoadingSpinner,
1916
EuiSpacer,
2017
EuiText,
@@ -33,7 +30,7 @@ import { SavedSearchQuery } from '../../../../../contexts/ml';
3330
import { getToastNotifications } from '../../../../../util/dependency_cache';
3431
import { ml } from '../../../../../services/ml_api_service';
3532

36-
import { defaultSearchQuery, useResultsViewConfig } from '../../../../common';
33+
import { getAnalysisType, defaultSearchQuery, useResultsViewConfig } from '../../../../common';
3734

3835
import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics';
3936

@@ -43,13 +40,88 @@ import {
4340
} from '../../../analytics_management/components/analytics_list/common';
4441
import { ExpandedRow } from '../../../analytics_management/components/analytics_list/expanded_row';
4542

46-
import { ExpandableSection } from '../expandable_section';
43+
import { ExpandableSection, ExpandableSectionProps } from '../expandable_section';
4744
import { ExplorationQueryBar } from '../exploration_query_bar';
4845
import { IndexPatternPrompt } from '../index_pattern_prompt';
4946

5047
import { getFeatureCount } from './common';
5148
import { useOutlierData } from './use_outlier_data';
5249

50+
const getAnalyticsSectionHeaderItems = (
51+
expandedRowItem: DataFrameAnalyticsListRow | undefined
52+
): ExpandableSectionProps['headerItems'] => {
53+
return expandedRowItem !== undefined
54+
? [
55+
{
56+
id: 'analysisTypeLabel',
57+
label: (
58+
<FormattedMessage
59+
id="xpack.ml.dataframe.analytics.exploration.analysisTypeLabel"
60+
defaultMessage="Type"
61+
/>
62+
),
63+
value: expandedRowItem.job_type,
64+
},
65+
{
66+
id: 'analysisSourceIndexLabel',
67+
label: (
68+
<FormattedMessage
69+
id="xpack.ml.dataframe.analytics.exploration.analysisSourceIndexLabel"
70+
defaultMessage="Source index"
71+
/>
72+
),
73+
value: expandedRowItem.config.source.index,
74+
},
75+
{
76+
id: 'analysisDestinationIndexLabel',
77+
label: (
78+
<FormattedMessage
79+
id="xpack.ml.dataframe.analytics.exploration.analysisDestinationIndexLabel"
80+
defaultMessage="Destination index"
81+
/>
82+
),
83+
value: expandedRowItem.config.dest.index,
84+
},
85+
]
86+
: 'loading';
87+
};
88+
89+
const getResultsSectionHeaderItems = (
90+
columnsWithCharts: EuiDataGridColumn[],
91+
tableItems: Array<Record<string, any>>,
92+
rowCount: number,
93+
colorRange: ReturnType<typeof useColorRange>
94+
): ExpandableSectionProps['headerItems'] => {
95+
return columnsWithCharts.length > 0 && tableItems.length > 0
96+
? [
97+
{
98+
id: 'explorationTableTotalDocs',
99+
label: (
100+
<FormattedMessage
101+
id="xpack.ml.dataframe.analytics.exploration.explorationTableTotalDocsLabel"
102+
defaultMessage="Total docs"
103+
/>
104+
),
105+
value: rowCount,
106+
},
107+
{
108+
id: 'colorRangeLegend',
109+
value: (
110+
<ColorRangeLegend
111+
colorRange={colorRange}
112+
title={i18n.translate(
113+
'xpack.ml.dataframe.analytics.exploration.colorRangeLegendTitle',
114+
{
115+
defaultMessage: 'Feature influence score',
116+
}
117+
)}
118+
/>
119+
),
120+
},
121+
]
122+
: 'loading';
123+
};
124+
53125
export type TableItem = Record<string, any>;
54126

55127
interface ExplorationProps {
@@ -90,7 +162,7 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
90162
checkpointing: {},
91163
config,
92164
id: config.id,
93-
job_type: Object.keys(config.analysis)[0] as DataFrameAnalysisConfigType,
165+
job_type: getAnalysisType(config.analysis) as DataFrameAnalysisConfigType,
94166
mode: DATA_FRAME_MODE.BATCH,
95167
state: stats.state,
96168
stats,
@@ -103,6 +175,55 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
103175
fetchStats();
104176
}, [jobConfig?.id]);
105177

178+
// Analytics section header items and content
179+
const analyticsSectionHeaderItems = getAnalyticsSectionHeaderItems(expandedRowItem);
180+
const analyticsSectionContent = (
181+
<>
182+
<EuiHorizontalRule size="full" margin="none" />
183+
{expandedRowItem === undefined && (
184+
<EuiText textAlign="center">
185+
<EuiSpacer size="l" />
186+
<EuiLoadingSpinner size="l" />
187+
<EuiSpacer size="l" />
188+
</EuiText>
189+
)}
190+
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
191+
indexPattern !== undefined &&
192+
jobConfig !== undefined &&
193+
columnsWithCharts.length > 0 &&
194+
tableItems.length > 0 &&
195+
expandedRowItem !== undefined && <ExpandedRow item={expandedRowItem} />}
196+
</>
197+
);
198+
199+
// Results section header items and content
200+
const resultsSectionHeaderItems = getResultsSectionHeaderItems(
201+
columnsWithCharts,
202+
tableItems,
203+
outlierData.rowCount,
204+
colorRange
205+
);
206+
const resultsSectionContent = (
207+
<>
208+
{jobConfig !== undefined && needsDestIndexPattern && (
209+
<IndexPatternPrompt destIndex={jobConfig.dest.index} />
210+
)}
211+
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
212+
indexPattern !== undefined && (
213+
<>
214+
<EuiSpacer size="s" />
215+
{columnsWithCharts.length > 0 && tableItems.length > 0 && (
216+
<DataGrid
217+
{...outlierData}
218+
dataTestSubj="mlExplorationDataGrid"
219+
toastNotifications={getToastNotifications()}
220+
/>
221+
)}
222+
</>
223+
)}
224+
</>
225+
);
226+
106227
return (
107228
<>
108229
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
@@ -114,66 +235,8 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
114235
)}
115236

116237
<ExpandableSection
117-
content={
118-
<>
119-
<EuiHorizontalRule size="full" margin="none" />
120-
{expandedRowItem === undefined && (
121-
<EuiText textAlign="center">
122-
<EuiSpacer size="l" />
123-
<EuiLoadingSpinner size="l" />
124-
<EuiSpacer size="l" />
125-
</EuiText>
126-
)}
127-
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
128-
indexPattern !== undefined &&
129-
jobConfig !== undefined &&
130-
columnsWithCharts.length > 0 &&
131-
tableItems.length > 0 &&
132-
expandedRowItem !== undefined && <ExpandedRow item={expandedRowItem} />}
133-
</>
134-
}
135-
headerContent={
136-
<>
137-
{expandedRowItem === undefined && <EuiLoadingContent lines={1} />}
138-
{expandedRowItem !== undefined && (
139-
<EuiFlexGroup>
140-
<EuiFlexItem grow={false}>
141-
<EuiText size="xs" color="subdued">
142-
<p>
143-
<FormattedMessage
144-
id="xpack.ml.dataframe.analytics.exploration.analysisTypeLabel"
145-
defaultMessage="Type"
146-
/>
147-
</p>
148-
</EuiText>
149-
<EuiBadge>{expandedRowItem.job_type}</EuiBadge>
150-
</EuiFlexItem>
151-
<EuiFlexItem grow={false}>
152-
<EuiText size="xs" color="subdued">
153-
<p>
154-
<FormattedMessage
155-
id="xpack.ml.dataframe.analytics.exploration.analysisSourceIndexLabel"
156-
defaultMessage="Source index"
157-
/>
158-
</p>
159-
</EuiText>
160-
<EuiBadge>{expandedRowItem.config.source.index}</EuiBadge>
161-
</EuiFlexItem>
162-
<EuiFlexItem grow={false}>
163-
<EuiText size="xs" color="subdued">
164-
<p>
165-
<FormattedMessage
166-
id="xpack.ml.dataframe.analytics.exploration.analysisDestinationIndexLabel"
167-
defaultMessage="Destination index"
168-
/>
169-
</p>
170-
</EuiText>
171-
<EuiBadge>{expandedRowItem.config.dest.index}</EuiBadge>
172-
</EuiFlexItem>
173-
</EuiFlexGroup>
174-
)}
175-
</>
176-
}
238+
content={analyticsSectionContent}
239+
headerItems={analyticsSectionHeaderItems}
177240
isExpanded={false}
178241
title={
179242
<FormattedMessage
@@ -182,61 +245,12 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
182245
/>
183246
}
184247
/>
248+
185249
<EuiSpacer size="m" />
250+
186251
<ExpandableSection
187-
content={
188-
<>
189-
{jobConfig !== undefined && needsDestIndexPattern && (
190-
<IndexPatternPrompt destIndex={jobConfig.dest.index} />
191-
)}
192-
{(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) &&
193-
indexPattern !== undefined && (
194-
<>
195-
<EuiSpacer size="s" />
196-
{columnsWithCharts.length > 0 && tableItems.length > 0 && (
197-
<DataGrid
198-
{...outlierData}
199-
dataTestSubj="mlExplorationDataGrid"
200-
toastNotifications={getToastNotifications()}
201-
/>
202-
)}
203-
</>
204-
)}
205-
</>
206-
}
207-
headerContent={
208-
<>
209-
{(columnsWithCharts.length === 0 || tableItems.length === 0) && (
210-
<EuiLoadingContent lines={1} />
211-
)}
212-
{columnsWithCharts.length > 0 && tableItems.length > 0 && (
213-
<EuiFlexGroup>
214-
<EuiFlexItem grow={false}>
215-
<EuiText size="xs" color="subdued">
216-
<p>
217-
<FormattedMessage
218-
id="xpack.ml.dataframe.analytics.exploration.explorationTableTotalDocsLabel"
219-
defaultMessage="Total docs"
220-
/>
221-
</p>
222-
</EuiText>
223-
<EuiBadge>{outlierData.rowCount}</EuiBadge>
224-
</EuiFlexItem>
225-
<EuiFlexItem>
226-
<ColorRangeLegend
227-
colorRange={colorRange}
228-
title={i18n.translate(
229-
'xpack.ml.dataframe.analytics.exploration.colorRangeLegendTitle',
230-
{
231-
defaultMessage: 'Feature influence score',
232-
}
233-
)}
234-
/>
235-
</EuiFlexItem>
236-
</EuiFlexGroup>
237-
)}
238-
</>
239-
}
252+
content={resultsSectionContent}
253+
headerItems={resultsSectionHeaderItems}
240254
title={
241255
<FormattedMessage
242256
id="xpack.ml.dataframe.analytics.exploration.explorationTableTitle"

0 commit comments

Comments
 (0)