Skip to content

Commit

Permalink
[ML] DF Analytics: Collapsable sections on results pages (elastic#76641)
Browse files Browse the repository at this point in the history
- Fixes cell color coding based on influence score for outlier detection results page data grid. (Part of elastic#77046)
- Introduces expandable sections (<ExpandableSection />). In contrast to plain accordions, the main idea of this component is that it should also provide some sort of useful summary when collapsed instead of just being an expandable title. For example, the "Analysis" section is collapsed by default, but still offers information like analysis type, source and destination index. This concept should allow us to keep the analytics results pages usable with more content (additional results, evaluations, visualizations) being added over time.
- The "Analysis" section is a reuse of the expandable row from the analytics jobs list. Some design adjustments have been made to make it usable in both places.
  • Loading branch information
walterra committed Oct 1, 2020
1 parent 6e49c40 commit 30a1a13
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React, { useEffect, useRef, FC } from 'react';
import d3 from 'd3';

import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { EuiText } from '@elastic/eui';

const COLOR_RANGE_RESOLUTION = 10;

Expand Down Expand Up @@ -134,15 +134,11 @@ export const ColorRangeLegend: FC<ColorRangeLegendProps> = ({
}

return (
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
<EuiText size="xs">
<strong>{title}</strong>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<svg ref={d3Container} />
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiText size="xs" color="subdued">
<p>{title}</p>
</EuiText>
<svg ref={d3Container} />
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export const EXTENDED_NUMERICAL_TYPES = new Set([

// eslint-disable-next-line @typescript-eslint/naming-convention
export const ML__ID_COPY = 'ml__id_copy';
// eslint-disable-next-line @typescript-eslint/naming-convention
export const ML__INCREMENTAL_ID = 'ml__incremental_id';

export const isKeywordAndTextType = (fieldName: string): boolean => {
const { fields } = newJobCapsService;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.mlExpandableSection {
padding: 0 $euiSizeS $euiSizeS $euiSizeS;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import './expandable_section.scss';

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

import {
EuiBadge,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiLoadingContent,
EuiPanel,
EuiText,
} from '@elastic/eui';

interface HeaderItem {
// id is used as the React key and to construct a data-test-subj
id: string;
label?: ReactNode;
value: ReactNode;
}

const isHeaderItems = (arg: any): arg is HeaderItem[] => {
return Array.isArray(arg);
};

export interface ExpandableSectionProps {
content: ReactNode;
headerItems?: HeaderItem[] | 'loading';
isExpanded?: boolean;
dataTestId: string;
title: ReactNode;
}

export const ExpandableSection: FC<ExpandableSectionProps> = ({
headerItems,
// For now we don't have a need for complete external control
// and just want to pass in a default value. If we wanted
// full external control we'd also need to add a onToggleExpanded()
// callback.
isExpanded: isExpandedDefault = true,
content,
dataTestId,
title,
}) => {
const [isExpanded, setIsExpanded] = useState(isExpandedDefault);
const toggleExpanded = () => {
setIsExpanded(!isExpanded);
};

return (
<EuiPanel paddingSize="none" data-test-subj={`mlDFExpandableSection-${dataTestId}`}>
<div className="mlExpandableSection">
<EuiButtonEmpty
onClick={toggleExpanded}
iconType={isExpanded ? 'arrowUp' : 'arrowDown'}
size="l"
iconSide="right"
flush="left"
>
{title}
</EuiButtonEmpty>
{headerItems === 'loading' && <EuiLoadingContent lines={1} />}
{isHeaderItems(headerItems) && (
<EuiFlexGroup>
{headerItems.map(({ label, value, id }) => (
<EuiFlexItem
grow={false}
key={id}
data-test-subj={`mlDFExpandableSectionItem-${dataTestId}-${id}`}
>
{label !== undefined && value !== undefined && (
<>
<EuiText size="xs" color="subdued">
<p>{label}</p>
</EuiText>
<EuiBadge>{value}</EuiBadge>
</>
)}
{label === undefined && value}
</EuiFlexItem>
))}
</EuiFlexGroup>
)}
</div>
{isExpanded && content}
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export { ExpandableSection, ExpandableSectionProps } from './expandable_section';
Loading

0 comments on commit 30a1a13

Please sign in to comment.