Skip to content

Commit

Permalink
[8.x] [ML] Single Metric Viewer embeddable: Add action for dashboard …
Browse files Browse the repository at this point in the history
…to apply filter from the embeddable to the page (#198869) (#200638)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[ML] Single Metric Viewer embeddable: Add action for dashboard to
apply filter from the embeddable to the page
(#198869)](#198869)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Melissa
Alvarez","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-11-18T19:08:20Z","message":"[ML]
Single Metric Viewer embeddable: Add action for dashboard to apply
filter from the embeddable to the page (#198869)\n\n##
Summary\r\n\r\nRelated meta issue:
https://github.com/elastic/kibana/issues/187483\r\n\r\nThis PR adds the
ability to add a filter and a negate filter to a\r\ndashboard via plus
and minus icons in the SMV embeddable panel.\r\nThis PR also updates the
behavior of the anomaly charts panel in\r\ndashboards so that the minus
icon works as a negate filter instead of\r\nremoving the filter. This
behavior is consistent with other plus/minus\r\nicons next to values in
dashboard panels.\r\n\r\nIn dashboard:\r\n\r\n<img width=\"1217\"
alt=\"Screenshot 2024-11-11 at 09 54
41\"\r\nsrc=\"https://github.com/user-attachments/assets/a8e12ce8-3794-4ddc-93da-e3d0bf139df7\">\r\n\r\n\r\nWith
a by and partition field:\r\n<img width=\"1214\" alt=\"Screenshot
2024-11-11 at 09 59
09\"\r\nsrc=\"https://github.com/user-attachments/assets/3b508a64-8bb1-4d89-89b2-9b8d195d1cbe\">\r\n\r\n\r\nIn
cases:\r\n\r\n<img width=\"1555\" alt=\"Screenshot 2024-11-11 at 10 00
41\"\r\nsrc=\"https://github.com/user-attachments/assets/1d1ac6d7-29c8-4e84-a758-3dfc293d58fe\">\r\n\r\n\r\nAnomaly
Charts in
explorer:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/6e738171-5f1a-46c2-bd34-2c8581f2a3e3)\r\n\r\nAnomaly
charts in
dashboard:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/5011b44c-0a33-42a2-a869-413d4fffe4ad)\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"f876540dc7fc935e9cc4b7d841247ce7bca5728d","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement",":ml","Feature:Anomaly
Detection","v9.0.0","Feature:Embeddables","backport:version","v8.17.0"],"title":"[ML]
Single Metric Viewer embeddable: Add action for dashboard to apply
filter from the embeddable to the
page","number":198869,"url":"https://github.com/elastic/kibana/pull/198869","mergeCommit":{"message":"[ML]
Single Metric Viewer embeddable: Add action for dashboard to apply
filter from the embeddable to the page (#198869)\n\n##
Summary\r\n\r\nRelated meta issue:
https://github.com/elastic/kibana/issues/187483\r\n\r\nThis PR adds the
ability to add a filter and a negate filter to a\r\ndashboard via plus
and minus icons in the SMV embeddable panel.\r\nThis PR also updates the
behavior of the anomaly charts panel in\r\ndashboards so that the minus
icon works as a negate filter instead of\r\nremoving the filter. This
behavior is consistent with other plus/minus\r\nicons next to values in
dashboard panels.\r\n\r\nIn dashboard:\r\n\r\n<img width=\"1217\"
alt=\"Screenshot 2024-11-11 at 09 54
41\"\r\nsrc=\"https://github.com/user-attachments/assets/a8e12ce8-3794-4ddc-93da-e3d0bf139df7\">\r\n\r\n\r\nWith
a by and partition field:\r\n<img width=\"1214\" alt=\"Screenshot
2024-11-11 at 09 59
09\"\r\nsrc=\"https://github.com/user-attachments/assets/3b508a64-8bb1-4d89-89b2-9b8d195d1cbe\">\r\n\r\n\r\nIn
cases:\r\n\r\n<img width=\"1555\" alt=\"Screenshot 2024-11-11 at 10 00
41\"\r\nsrc=\"https://github.com/user-attachments/assets/1d1ac6d7-29c8-4e84-a758-3dfc293d58fe\">\r\n\r\n\r\nAnomaly
Charts in
explorer:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/6e738171-5f1a-46c2-bd34-2c8581f2a3e3)\r\n\r\nAnomaly
charts in
dashboard:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/5011b44c-0a33-42a2-a869-413d4fffe4ad)\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"f876540dc7fc935e9cc4b7d841247ce7bca5728d"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/198869","number":198869,"mergeCommit":{"message":"[ML]
Single Metric Viewer embeddable: Add action for dashboard to apply
filter from the embeddable to the page (#198869)\n\n##
Summary\r\n\r\nRelated meta issue:
https://github.com/elastic/kibana/issues/187483\r\n\r\nThis PR adds the
ability to add a filter and a negate filter to a\r\ndashboard via plus
and minus icons in the SMV embeddable panel.\r\nThis PR also updates the
behavior of the anomaly charts panel in\r\ndashboards so that the minus
icon works as a negate filter instead of\r\nremoving the filter. This
behavior is consistent with other plus/minus\r\nicons next to values in
dashboard panels.\r\n\r\nIn dashboard:\r\n\r\n<img width=\"1217\"
alt=\"Screenshot 2024-11-11 at 09 54
41\"\r\nsrc=\"https://github.com/user-attachments/assets/a8e12ce8-3794-4ddc-93da-e3d0bf139df7\">\r\n\r\n\r\nWith
a by and partition field:\r\n<img width=\"1214\" alt=\"Screenshot
2024-11-11 at 09 59
09\"\r\nsrc=\"https://github.com/user-attachments/assets/3b508a64-8bb1-4d89-89b2-9b8d195d1cbe\">\r\n\r\n\r\nIn
cases:\r\n\r\n<img width=\"1555\" alt=\"Screenshot 2024-11-11 at 10 00
41\"\r\nsrc=\"https://github.com/user-attachments/assets/1d1ac6d7-29c8-4e84-a758-3dfc293d58fe\">\r\n\r\n\r\nAnomaly
Charts in
explorer:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/6e738171-5f1a-46c2-bd34-2c8581f2a3e3)\r\n\r\nAnomaly
charts in
dashboard:\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/5011b44c-0a33-42a2-a869-413d4fffe4ad)\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"f876540dc7fc935e9cc4b7d841247ce7bca5728d"}},{"branch":"8.x","label":"v8.17.0","branchLabelMappingKey":"^v8.17.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Melissa Alvarez <[email protected]>
  • Loading branch information
kibanamachine and alvarezmelissa87 authored Nov 18, 2024
1 parent 7c5c0fc commit 852d6d9
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@ interface EntityFilterProps {
}) => void;
influencerFieldName: string;
influencerFieldValue: string;
isEmbeddable?: boolean;
}
export const EntityFilter: FC<EntityFilterProps> = ({
onFilter,
influencerFieldName,
influencerFieldValue,
isEmbeddable,
}) => {
return (
<React.Fragment>
<EuiToolTip
content={
<FormattedMessage
id="xpack.ml.entityFilter.addFilterTooltip"
defaultMessage="Add filter"
defaultMessage="Filter for"
/>
}
>
Expand All @@ -57,10 +59,17 @@ export const EntityFilter: FC<EntityFilterProps> = ({
</EuiToolTip>
<EuiToolTip
content={
<FormattedMessage
id="xpack.ml.entityFilter.removeFilterTooltip"
defaultMessage="Remove filter"
/>
isEmbeddable ? (
<FormattedMessage
id="xpack.ml.entityFilter.filterOutTooltip"
defaultMessage={'Filter out'}
/>
) : (
<FormattedMessage
id="xpack.ml.entityFilter.removeFilterTooltip"
defaultMessage={'Remove filter'}
/>
)
}
>
<EuiButtonIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function ExplorerChartLabel({
detectorLabel,
entityFields,
infoTooltip,
isEmbeddable,
wrapLabel = false,
onSelectEntity,
}) {
Expand All @@ -34,9 +35,9 @@ export function ExplorerChartLabel({
// Using &nbsp;s here to make sure those spaces get rendered.
const labelSeparator =
wrapLabel === true || entityFields.length === 0 || detectorLabel.length === 0 ? (
<React.Fragment>&nbsp;</React.Fragment>
<>&nbsp;</>
) : (
<React.Fragment>&nbsp;&ndash;&nbsp;</React.Fragment>
<>&nbsp;&ndash;&nbsp;</>
);

const applyFilter = useCallback(
Expand All @@ -52,6 +53,7 @@ export function ExplorerChartLabel({
<ExplorerChartLabelBadge entity={entity} />
{onSelectEntity !== undefined && (
<EntityFilter
isEmbeddable={isEmbeddable}
onFilter={applyFilter}
influencerFieldName={entity.fieldName}
influencerFieldValue={entity.fieldValue}
Expand All @@ -73,25 +75,26 @@ export function ExplorerChartLabel({
);

return (
<React.Fragment>
<>
<span className="ml-explorer-chart-label">
<span className="ml-explorer-chart-label-detector">
{detectorLabel}
{labelSeparator}
</span>
{wrapLabel && infoIcon}
{!wrapLabel && (
<React.Fragment>
<>
{entityFieldBadges} {infoIcon}
</React.Fragment>
</>
)}
</span>
{wrapLabel && <span className="ml-explorer-chart-label-badges">{entityFieldBadges}</span>}
</React.Fragment>
</>
);
}
ExplorerChartLabel.propTypes = {
detectorLabel: PropTypes.object.isRequired,
isEmbeddable: PropTypes.boolean,
entityFields: PropTypes.arrayOf(ExplorerChartLabelBadge.propTypes.entity),
infoTooltip: PropTypes.object.isRequired,
wrapLabel: PropTypes.bool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export const ExplorerAnomaliesContainer: FC<ExplorerAnomaliesContainerProps> = (
<ExplorerChartsContainer
{...{
...chartsData,
isEmbeddable: true,
severity: severity.val,
mlLocator,
tableData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function getChartId(series, randomId) {
// Wrapper for a single explorer chart
function ExplorerChartContainer({
id,
isEmbeddable,
series,
severity,
tooManyBuckets,
Expand Down Expand Up @@ -251,6 +252,7 @@ function ExplorerChartContainer({
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<ExplorerChartLabel
isEmbeddable={isEmbeddable}
detectorLabel={DetectorLabel}
entityFields={entityFields}
infoTooltip={{ ...series.infoTooltip, chartType }}
Expand Down Expand Up @@ -376,6 +378,7 @@ function ExplorerChartContainer({
// Flex layout wrapper for all explorer charts
export const ExplorerChartsContainerUI = ({
id: uuid,
isEmbeddable,
chartsPerRow,
seriesToPlot,
severity,
Expand Down Expand Up @@ -443,6 +446,7 @@ export const ExplorerChartsContainerUI = ({
<ExplorerChartContainer
key={chartId}
id={chartId}
isEmbeddable={isEmbeddable}
series={series}
severity={severity}
tooManyBuckets={tooManyBuckets}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { context } from '@kbn/kibana-react-plugin/public';
import { ML_JOB_AGGREGATION, aggregationTypeTransform } from '@kbn/ml-anomaly-utils';

import {
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
EuiTitle,
EuiTextColor,
} from '@elastic/eui';
import { TimeSeriesExplorerHelpPopover } from '../timeseriesexplorer_help_popover';
import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';

import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../../common/constants/search';
import {
Expand Down Expand Up @@ -67,16 +59,11 @@ import { timeSeriesExplorerServiceFactory } from '../../util/time_series_explore
import { getTimeseriesexplorerDefaultState } from '../timeseriesexplorer_utils';
import { mlJobServiceFactory } from '../../services/job_service';
import { forecastServiceFactory } from '../../services/forecast_service';

// Used to indicate the chart is being plotted across
// all partition field values, where the cardinality of the field cannot be
// obtained as it is not aggregatable e.g. 'all distinct kpi_indicator values'
const allValuesLabel = i18n.translate('xpack.ml.timeSeriesExplorer.allPartitionValuesLabel', {
defaultMessage: 'all',
});
import { SingleMetricViewerTitle } from './timeseriesexplorer_title';

export class TimeSeriesExplorerEmbeddableChart extends React.Component {
static propTypes = {
api: PropTypes.object,
appStateHandler: PropTypes.func.isRequired,
autoZoomDuration: PropTypes.number.isRequired,
bounds: PropTypes.object.isRequired,
Expand Down Expand Up @@ -930,70 +917,11 @@ export class TimeSeriesExplorerEmbeddableChart extends React.Component {
(fullRefresh === false || loading === false) &&
hasResults === true && (
<div>
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiTitle size={'xs'}>
<h2>
<span>
{i18n.translate(
'xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle',
{
defaultMessage: 'Single time series analysis of {functionLabel}',
values: { functionLabel: chartDetails.functionLabel },
}
)}
</span>
&nbsp;
{chartDetails.entityData.count === 1 && (
<EuiTextColor color={'success'} size={'s'} component={'span'}>
{chartDetails.entityData.entities.length > 0 && '('}
{chartDetails.entityData.entities
.map((entity) => {
return `${entity.fieldName}: ${entity.fieldValue}`;
})
.join(', ')}
{chartDetails.entityData.entities.length > 0 && ')'}
</EuiTextColor>
)}
{chartDetails.entityData.count !== 1 && (
<EuiTextColor color={'success'} size={'s'} component={'span'}>
{chartDetails.entityData.entities.map((countData, i) => {
return (
<Fragment key={countData.fieldName}>
{i18n.translate(
'xpack.ml.timeSeriesExplorer.countDataInChartDetailsDescription',
{
defaultMessage:
'{openBrace}{cardinalityValue} distinct {fieldName} {cardinality, plural, one {} other { values}}{closeBrace}',
values: {
openBrace: i === 0 ? '(' : '',
closeBrace:
i === chartDetails.entityData.entities.length - 1
? ')'
: '',
cardinalityValue:
countData.cardinality === 0
? allValuesLabel
: countData.cardinality,
cardinality: countData.cardinality,
fieldName: countData.fieldName,
},
}
)}
{i !== chartDetails.entityData.entities.length - 1 ? ', ' : ''}
</Fragment>
);
})}
</EuiTextColor>
)}
</h2>
</EuiTitle>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<TimeSeriesExplorerHelpPopover embeddableMode />
</EuiFlexItem>
</EuiFlexGroup>
<SingleMetricViewerTitle
api={this.props.api}
functionLabel={chartDetails.functionLabel}
entityData={chartDetails.entityData}
/>
<EuiFlexGroup style={{ float: 'right' }} alignItems="center">
{showModelBoundsCheckbox && (
<TimeseriesExplorerCheckbox
Expand Down
Loading

0 comments on commit 852d6d9

Please sign in to comment.