Skip to content

Commit 0cc887b

Browse files
rbrtjkibanamachine
andauthored
[ML][UX]: Consistent Layout and UI Enhancements for ML Pages (#203813)
## Summary * Updated alignment for `Add to` action buttons across various ML pages - see: #184109 * Fixed the overflowing date picker on `Anomaly Detection` pages - see: [#204394](#204394) * Standardized gaps around items on pages to maintain consistent values of `8px` (`gutterSize = 's'`) * Fixed the header on the Data Visualizer page - see: [#204393](#204393) * Adjusted the layout for Change Point Detection * Updated toast messages & toast action button - see: #184109 * Added icons for attachments actions Exploration around new `Add to` actions buttons - the right column is the most recent one, see: #184109 : | Before | After (add_to button) | After (icon button) - current | | ------------- | ------------- | ------------- | | ![Screenshot 2024-12-12 at 11 45 14](https://github.com/user-attachments/assets/08dc0be5-0b98-481d-9906-d3434f03f634) | ![Screenshot 2024-12-12 at 11 37 38](https://github.com/user-attachments/assets/0b2cbdcd-cad0-49aa-842f-123eebec1716) | ![Screenshot 2024-12-12 at 12 42 58](https://github.com/user-attachments/assets/c0a0c732-bbc0-4007-998e-df413fae612b) | | ![Screenshot 2024-12-12 at 11 45 49](https://github.com/user-attachments/assets/9ff45cf8-1c24-4ef4-ab59-2b54f1569c6e) | ![Screenshot 2024-12-12 at 11 39 34](https://github.com/user-attachments/assets/293255eb-eba5-4d90-a10b-0f41de0cc195) | ![Screenshot 2024-12-12 at 12 44 58](https://github.com/user-attachments/assets/740da2fb-ceed-4e6a-add6-9a8d695776a6) | | ![Screenshot 2024-12-12 at 11 46 30](https://github.com/user-attachments/assets/71cea9f4-7658-4776-865d-0f7c5682e67a) | ![Screenshot 2024-12-12 at 11 40 18](https://github.com/user-attachments/assets/b03e8a75-68d3-4c26-942c-1d41072a62ee) | ![image](https://github.com/user-attachments/assets/6a259924-7081-426c-8bd2-346e4f0ae152) | | ![Screenshot 2024-12-12 at 11 48 07](https://github.com/user-attachments/assets/2b340d38-26a5-45bc-851e-8b1956503500) | ![Screenshot 2024-12-12 at 11 42 03](https://github.com/user-attachments/assets/ecef0b37-a43c-42a3-911f-31d4acf9ac7b) | ![Screenshot 2024-12-12 at 12 46 14](https://github.com/user-attachments/assets/f9dddfe0-7296-4394-bb2f-94d702361f49) | | ![Screenshot 2024-12-12 at 11 49 05](https://github.com/user-attachments/assets/d670ad40-58d4-40fb-a88d-7ac5e6c1fbbd) | ![Screenshot 2024-12-12 at 11 43 40](https://github.com/user-attachments/assets/856f9476-c6ff-4405-8865-fb8784f3d818) | ![image](https://github.com/user-attachments/assets/b18f624b-e648-403f-9595-442b2723bdde) | Toasts: | Before | After | | ------ | ------ | | <img width="376" alt="image" src="https://github.com/user-attachments/assets/c58000c2-30d4-4312-be53-0e3e9a6e3ae6" /> | ![image](https://github.com/user-attachments/assets/36955456-026a-4abe-b872-c72c115a2dbe) | Other changes: | Before | After | | ------ | ------ | | ![Screenshot 2024-12-13 at 17 57 36](https://github.com/user-attachments/assets/263940ea-9396-4f82-b14e-c9086c6d36e8) | ![Screenshot 2024-12-13 at 18 00 26](https://github.com/user-attachments/assets/49430be4-356b-4902-b855-7fc1b252fbdb) | | ![Screenshot 2024-12-13 at 18 06 59](https://github.com/user-attachments/assets/67ad0faf-42f7-44e1-9290-857e28a9d5e4) | ![Screenshot 2024-12-13 at 18 02 04](https://github.com/user-attachments/assets/357d7296-7b5f-4df5-b664-8bd99c93205b) | | ![Screenshot 2024-12-13 at 18 08 20](https://github.com/user-attachments/assets/819a7c33-9c7a-4423-be1b-cbec30dd8a97) | ![Screenshot 2024-12-13 at 18 09 30](https://github.com/user-attachments/assets/c4b3cb40-f572-4828-888b-4cfff6b565b9) | | ![Screenshot 2024-12-13 at 18 11 52](https://github.com/user-attachments/assets/c63ccdf3-aeaa-4047-a3b5-f67c11690020) | ![Screenshot 2024-12-13 at 18 10 34](https://github.com/user-attachments/assets/6a6343d5-a7f7-45da-bf40-46b14b257e41) | | ![Screenshot 2024-12-13 at 18 30 32](https://github.com/user-attachments/assets/7aa13ad8-ba6f-4801-b0fe-ff90dd9038c1) | ![Screenshot 2024-12-13 at 18 32 59](https://github.com/user-attachments/assets/17774c78-003d-46fd-b7bb-d21cdee7df47) | | ![Screenshot 2024-12-13 at 18 35 56](https://github.com/user-attachments/assets/b7b003c6-11a6-4a1d-97c2-c1b920c0fd1a) | ![Screenshot 2024-12-13 at 18 34 25](https://github.com/user-attachments/assets/5af49323-cb9c-433d-aa6f-91af21dfa5bf) | | <img width="342" alt="image" src="https://github.com/user-attachments/assets/6529eebe-510e-4688-81e6-4cf3e880c610" /> | <img width="323" alt="image" src="https://github.com/user-attachments/assets/6dada83e-252f-45d5-95d2-a03fa856d70a" /> | - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --------- Co-authored-by: kibanamachine <[email protected]>
1 parent 3dcae51 commit 0cc887b

File tree

25 files changed

+447
-260
lines changed

25 files changed

+447
-260
lines changed

x-pack/platform/packages/private/ml/date_picker/src/components/date_picker_wrapper.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@ interface DatePickerWrapperProps {
8787
* Width setting to be passed on to `EuiSuperDatePicker`
8888
*/
8989
width?: EuiSuperDatePickerProps['width'];
90-
/**
91-
* Boolean flag to set use of flex group wrapper
92-
*/
93-
flexGroup?: boolean;
9490
/**
9591
* Boolean flag to disable the date picker
9692
*/
@@ -123,7 +119,6 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
123119
isLoading = false,
124120
showRefresh,
125121
width,
126-
flexGroup = true,
127122
isDisabled = false,
128123
needsUpdate,
129124
onRefresh,
@@ -363,6 +358,8 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
363358
</>
364359
);
365360

361+
const flexGroup = !isTimeRangeSelectorEnabled || isAutoRefreshOnly === true;
362+
366363
const wrapped = flexGroup ? (
367364
<EuiFlexGroup gutterSize="s" alignItems="center">
368365
{flexItems}

x-pack/platform/packages/private/ml/date_picker/src/components/full_time_range_selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
220220
}, [frozenDataPreference, showFrozenDataTierChoice]);
221221

222222
return (
223-
<EuiFlexGroup responsive={false} gutterSize="xs">
223+
<EuiFlexGroup responsive={false} gutterSize="s">
224224
<EuiToolTip content={buttonTooltip}>
225225
<EuiButton
226226
isDisabled={disabled}

x-pack/platform/plugins/private/data_visualizer/public/application/data_drift/data_drift_page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ export const PageHeader: FC<PageHeaderProps> = ({ onRefresh, needsUpdate }) => {
115115
isAutoRefreshOnly={!hasValidTimeField}
116116
showRefresh={!hasValidTimeField}
117117
width="full"
118-
flexGroup={!hasValidTimeField}
119118
onRefresh={onRefresh}
120119
needsUpdate={needsUpdate}
121120
/>,

x-pack/platform/plugins/private/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type { Required } from 'utility-types';
1212
import { getEsQueryConfig } from '@kbn/data-plugin/common';
1313

1414
import {
15-
useEuiTheme,
1615
useEuiBreakpoint,
1716
useIsWithinMaxBreakpoint,
1817
EuiFlexGroup,
@@ -21,7 +20,6 @@ import {
2120
EuiPanel,
2221
EuiProgress,
2322
EuiSpacer,
24-
EuiTitle,
2523
} from '@elastic/eui';
2624

2725
import { type Filter, FilterStateStore, type Query, buildEsQuery } from '@kbn/es-query';
@@ -108,8 +106,6 @@ export interface IndexDataVisualizerViewProps {
108106
}
109107

110108
export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVisualizerProps) => {
111-
const { euiTheme } = useEuiTheme();
112-
113109
const [savedRandomSamplerPreference, saveRandomSamplerPreference] = useStorage<
114110
DVKey,
115111
DVStorageMapped<typeof DV_RANDOM_SAMPLER_PREFERENCE>
@@ -515,49 +511,40 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
515511
paddingSize="none"
516512
>
517513
<EuiPageTemplate.Section>
518-
<EuiPageTemplate.Header data-test-subj="dataVisualizerPageHeader" css={dvPageHeader}>
519-
<EuiFlexGroup
520-
data-test-subj="dataViewTitleHeader"
521-
direction="row"
522-
alignItems="center"
523-
css={{ padding: `${euiTheme.size.s} 0`, marginRight: `${euiTheme.size.base}` }}
524-
>
525-
<EuiTitle size={'s'}>
526-
<h2>{currentDataView.getName()}</h2>
527-
</EuiTitle>
528-
<DataVisualizerDataViewManagement currentDataView={currentDataView} />
529-
</EuiFlexGroup>
530-
531-
{isWithinLargeBreakpoint ? <EuiSpacer size="m" /> : null}
532-
<EuiFlexGroup
533-
alignItems="center"
534-
justifyContent="flexEnd"
535-
gutterSize="s"
536-
data-test-subj="dataVisualizerTimeRangeSelectorSection"
537-
>
538-
{hasValidTimeField ? (
539-
<EuiFlexItem grow={false}>
540-
<FullTimeRangeSelector
541-
frozenDataPreference={frozenDataPreference}
542-
setFrozenDataPreference={setFrozenDataPreference}
543-
dataView={currentDataView}
544-
query={undefined}
545-
disabled={false}
546-
timefilter={timefilter}
547-
/>
548-
</EuiFlexItem>
549-
) : null}
550-
<EuiFlexItem grow={false}>
551-
<DatePickerWrapper
552-
isAutoRefreshOnly={!hasValidTimeField}
553-
showRefresh={!hasValidTimeField}
554-
width="full"
555-
needsUpdate={queryNeedsUpdate}
556-
onRefresh={handleRefresh}
514+
<EuiPageTemplate.Header
515+
data-test-subj="dataVisualizerPageHeader"
516+
css={dvPageHeader}
517+
pageTitle={
518+
<>
519+
{currentDataView.getName()}
520+
{/* TODO: This management section shouldn't live inside the header */}
521+
<DataVisualizerDataViewManagement currentDataView={currentDataView} />
522+
</>
523+
}
524+
rightSideGroupProps={{
525+
gutterSize: 's',
526+
'data-test-subj': 'dataVisualizerTimeRangeSelectorSection',
527+
}}
528+
rightSideItems={[
529+
<DatePickerWrapper
530+
isAutoRefreshOnly={!hasValidTimeField}
531+
showRefresh={!hasValidTimeField}
532+
width="full"
533+
needsUpdate={queryNeedsUpdate}
534+
onRefresh={handleRefresh}
535+
/>,
536+
hasValidTimeField && (
537+
<FullTimeRangeSelector
538+
frozenDataPreference={frozenDataPreference}
539+
setFrozenDataPreference={setFrozenDataPreference}
540+
dataView={currentDataView}
541+
query={undefined}
542+
disabled={false}
543+
timefilter={timefilter}
557544
/>
558-
</EuiFlexItem>
559-
</EuiFlexGroup>
560-
</EuiPageTemplate.Header>
545+
),
546+
]}
547+
/>
561548
<EuiSpacer size="m" />
562549

563550
<EuiFlexGroup gutterSize="m" direction={isWithinLargeBreakpoint ? 'column' : 'row'}>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { ChangePointDetectionViewType } from '@kbn/aiops-change-point-detection/constants';
9+
import { i18n } from '@kbn/i18n';
10+
11+
/**
12+
* Titles for the cases toast messages
13+
*/
14+
export const CASES_TOAST_MESSAGES_TITLES = {
15+
CHANGE_POINT_DETECTION: (viewType: ChangePointDetectionViewType, chartsCount: number) =>
16+
viewType === 'table'
17+
? i18n.translate('xpack.aiops.cases.changePointDetectionTableTitle', {
18+
defaultMessage: 'Change point table',
19+
})
20+
: i18n.translate('xpack.aiops.cases.changePointDetectionChartsTitle', {
21+
defaultMessage: 'Change point {chartsCount, plural, one {chart} other {charts}}',
22+
values: {
23+
chartsCount,
24+
},
25+
}),
26+
LOG_RATE_ANALYSIS: i18n.translate('xpack.aiops.cases.logRateAnalysisTitle', {
27+
defaultMessage: 'Log rate analysis',
28+
}),
29+
PATTERN_ANALYSIS: i18n.translate('xpack.aiops.cases.logPatternAnalysisTitle', {
30+
defaultMessage: 'Log pattern analysis',
31+
}),
32+
};

x-pack/platform/plugins/shared/aiops/public/components/change_point_detection/fields_config.tsx

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import {
5656
import { useChangePointResults } from './use_change_point_agg_request';
5757
import { useSplitFieldCardinality } from './use_split_field_cardinality';
5858
import { ViewTypeSelector } from './view_type_selector';
59+
import { CASES_TOAST_MESSAGES_TITLES } from '../../cases/constants';
5960

6061
const selectControlCss = { width: '350px' };
6162

@@ -215,12 +216,18 @@ const FieldPanel: FC<FieldPanelProps> = ({
215216
progress,
216217
} = useChangePointResults(fieldConfig, requestParams, combinedQuery, splitFieldCardinality);
217218

218-
const openCasesModalCallback = useCasesModal(EMBEDDABLE_CHANGE_POINT_CHART_TYPE);
219-
220219
const selectedPartitions = useMemo(() => {
221220
return (selectedChangePoints[panelIndex] ?? []).map((v) => v.group?.value as string);
222221
}, [selectedChangePoints, panelIndex]);
223222

223+
const openCasesModalCallback = useCasesModal(
224+
EMBEDDABLE_CHANGE_POINT_CHART_TYPE,
225+
CASES_TOAST_MESSAGES_TITLES.CHANGE_POINT_DETECTION(
226+
caseAttachment.viewType,
227+
selectedPartitions.length
228+
)
229+
);
230+
224231
const caseAttachmentButtonDisabled =
225232
isDefined(fieldConfig.splitField) && selectedPartitions.length === 0;
226233

@@ -283,6 +290,7 @@ const FieldPanel: FC<FieldPanelProps> = ({
283290
defaultMessage: 'To dashboard',
284291
}),
285292
panel: 'attachToDashboardPanel',
293+
icon: 'dashboardApp',
286294
'data-test-subj': 'aiopsChangePointDetectionAttachToDashboardButton',
287295
},
288296
]
@@ -307,6 +315,7 @@ const FieldPanel: FC<FieldPanelProps> = ({
307315
: {}),
308316
'data-test-subj': 'aiopsChangePointDetectionAttachToCaseButton',
309317
panel: 'attachToCasePanel',
318+
icon: 'casesApp',
310319
},
311320
]
312321
: []),
@@ -513,42 +522,37 @@ const FieldPanel: FC<FieldPanelProps> = ({
513522

514523
return (
515524
<EuiPanel paddingSize="s" hasBorder hasShadow={false} data-test-subj={dataTestSubj}>
516-
<EuiFlexGroup alignItems={'center'} justifyContent={'spaceBetween'} gutterSize={'s'}>
525+
<EuiFlexGroup alignItems={'flexStart'} justifyContent={'spaceBetween'} gutterSize={'s'}>
517526
<EuiFlexItem grow={false}>
518-
<EuiFlexGroup alignItems={'center'} gutterSize={'s'}>
519-
<EuiFlexItem grow={false}>
520-
<EuiButtonIcon
521-
data-test-subj="aiopsChangePointDetectionExpandConfigButton"
522-
iconType={isExpanded ? 'arrowDown' : 'arrowRight'}
523-
onClick={setIsExpanded.bind(null, (prevState) => !prevState)}
524-
aria-label={i18n.translate('xpack.aiops.changePointDetection.expandConfigLabel', {
525-
defaultMessage: 'Expand configuration',
526-
})}
527-
/>
528-
</EuiFlexItem>
529-
<EuiFlexItem grow={false}>
530-
<FieldsControls fieldConfig={fieldConfig} onChange={onChange}>
531-
<EuiFlexItem
532-
css={{ visibility: progress === null ? 'hidden' : 'visible' }}
533-
grow={true}
534-
>
535-
<EuiProgress
536-
label={
537-
<FormattedMessage
538-
id="xpack.aiops.changePointDetection.progressBarLabel"
539-
defaultMessage="Fetching change points"
540-
/>
541-
}
542-
value={progress ?? 0}
543-
max={100}
544-
valueText
545-
size="m"
527+
<EuiButtonIcon
528+
data-test-subj="aiopsChangePointDetectionExpandConfigButton"
529+
iconType={isExpanded ? 'arrowDown' : 'arrowRight'}
530+
onClick={setIsExpanded.bind(null, (prevState) => !prevState)}
531+
aria-label={i18n.translate('xpack.aiops.changePointDetection.expandConfigLabel', {
532+
defaultMessage: 'Expand configuration',
533+
})}
534+
size="s"
535+
/>
536+
</EuiFlexItem>
537+
538+
<EuiFlexItem>
539+
<FieldsControls fieldConfig={fieldConfig} onChange={onChange} data-test-subj="blablabla">
540+
<EuiFlexItem {...(progress === null && { css: { display: 'none' } })} grow={true}>
541+
<EuiProgress
542+
label={
543+
<FormattedMessage
544+
id="xpack.aiops.changePointDetection.progressBarLabel"
545+
defaultMessage="Fetching change points"
546546
/>
547-
<EuiSpacer size="s" />
548-
</EuiFlexItem>
549-
</FieldsControls>
547+
}
548+
value={progress ?? 0}
549+
max={100}
550+
valueText
551+
size="m"
552+
/>
553+
<EuiSpacer size="s" />
550554
</EuiFlexItem>
551-
</EuiFlexGroup>
555+
</FieldsControls>
552556
</EuiFlexItem>
553557

554558
<EuiFlexItem grow={false}>
@@ -565,8 +569,11 @@ const FieldPanel: FC<FieldPanelProps> = ({
565569
defaultMessage: 'Context menu',
566570
}
567571
)}
568-
iconType="boxesHorizontal"
569572
color="text"
573+
display="base"
574+
size="s"
575+
isSelected={isActionMenuOpen}
576+
iconType="boxesHorizontal"
570577
onClick={setIsActionMenuOpen.bind(null, !isActionMenuOpen)}
571578
/>
572579
}
@@ -678,7 +685,7 @@ export const FieldsControls: FC<PropsWithChildren<FieldsControlsProps>> = ({
678685
: undefined
679686
}
680687
>
681-
<EuiFlexGroup alignItems={'center'} responsive={true} wrap={true} gutterSize={'m'}>
688+
<EuiFlexGroup alignItems={'center'} responsive={true} wrap={true} gutterSize={'s'}>
682689
<EuiFlexItem grow={false} css={{ width: '200px' }}>
683690
<FunctionPicker value={fieldConfig.fn} onChange={(v) => onChangeFn('fn', v)} />
684691
</EuiFlexItem>

x-pack/platform/plugins/shared/aiops/public/components/log_categorization/attachments_menu.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import type { PatternAnalysisEmbeddableState } from '../../embeddables/pattern_a
3434
import type { RandomSamplerOption, RandomSamplerProbability } from './sampling_menu/random_sampler';
3535
import { useCasesModal } from '../../hooks/use_cases_modal';
3636
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
37+
import { CASES_TOAST_MESSAGES_TITLES } from '../../cases/constants';
3738

3839
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
3940

@@ -66,7 +67,10 @@ export const AttachmentsMenu = ({
6667
update: false,
6768
};
6869

69-
const openCasesModalCallback = useCasesModal(EMBEDDABLE_PATTERN_ANALYSIS_TYPE);
70+
const openCasesModalCallback = useCasesModal(
71+
EMBEDDABLE_PATTERN_ANALYSIS_TYPE,
72+
CASES_TOAST_MESSAGES_TITLES.PATTERN_ANALYSIS
73+
);
7074

7175
const timeRange = useTimeRangeUpdates();
7276

@@ -123,6 +127,7 @@ export const AttachmentsMenu = ({
123127
defaultMessage: 'Add to dashboard',
124128
}),
125129
panel: 'attachToDashboardPanel',
130+
icon: 'dashboardApp',
126131
'data-test-subj': 'aiopsLogPatternAnalysisAttachToDashboardButton',
127132
},
128133
]
@@ -133,6 +138,7 @@ export const AttachmentsMenu = ({
133138
name: i18n.translate('xpack.aiops.logCategorization.attachToCaseLabel', {
134139
defaultMessage: 'Add to case',
135140
}),
141+
icon: 'casesApp',
136142
'data-test-subj': 'aiopsLogPatternAnalysisAttachToCaseButton',
137143
onClick: () => {
138144
setIsActionMenuOpen(false);
@@ -218,8 +224,11 @@ export const AttachmentsMenu = ({
218224
defaultMessage: 'Attachments',
219225
}
220226
)}
221-
iconType="boxesHorizontal"
227+
size="m"
222228
color="text"
229+
display="base"
230+
isSelected={isActionMenuOpen}
231+
iconType="boxesHorizontal"
223232
onClick={() => setIsActionMenuOpen(!isActionMenuOpen)}
224233
/>
225234
}

0 commit comments

Comments
 (0)