Skip to content

Commit

Permalink
Merge branch 'main' into extend-elastic-query-rule
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Mar 31, 2022
2 parents f38e2e1 + c2db728 commit f0b8602
Show file tree
Hide file tree
Showing 24 changed files with 298 additions and 62 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ export const gaugeFunction = (): GaugeExpressionFunctionDefinition => ({
defaultMessage: 'Enables relative precentage mode',
}),
},
respectRanges: {
types: ['boolean'],
default: false,
help: i18n.translate('expressionGauge.functions.gauge.respectRanges.help', {
defaultMessage: 'Respect max and min values from ranges',
}),
},
commonLabel: {
types: ['string'],
help: i18n.translate('expressionGauge.functions.gauge.args.commonLabel.help', {
Expand All @@ -173,7 +180,6 @@ export const gaugeFunction = (): GaugeExpressionFunctionDefinition => ({
}),
},
},

fn(data, args, handlers) {
validateAccessor(args.metric, data.columns);
validateAccessor(args.min, data.columns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface GaugeState {
shape: GaugeShape;
/** @deprecated This field is deprecated and going to be removed in the futher release versions. */
percentageMode?: boolean;
respectRanges?: boolean;
commonLabel?: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
}

const goal = accessors.goal ? getValueFromAccessor(accessors.goal, row) : undefined;
const min = getMinValue(row, accessors);
const max = getMaxValue(row, accessors);
const min = getMinValue(row, accessors, palette?.params, args.respectRanges);
const max = getMaxValue(row, accessors, palette?.params, args.respectRanges);

if (min === max) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ describe('expression gauge utils', () => {
expect(getMaxValue({ min: 0 }, localAccessors)).toEqual(100);
expect(getMaxValue({}, localAccessors)).toEqual(100);
});
it('returns correct value if isRespectRanges is true and color palette was provided', () => {
expect(getMaxValue({ metric: 10 }, accessors, { rangeMax: 5 }, true)).toEqual(10);
expect(getMaxValue({ metric: 2 }, accessors, { rangeMax: 5 }, true)).toEqual(5);
});
it('returns correct value for multiple cases', () => {
const localAccessors = { ...accessors, max: 'max' };
expect(getMaxValue({ metric: 10 }, localAccessors)).toEqual(15);
Expand Down Expand Up @@ -76,6 +80,13 @@ describe('expression gauge utils', () => {
expect(getMinValue({ metric: -1000 }, localAccessors)).toEqual(-1010);
expect(getMinValue({ max: 1000, metric: 1.5 }, localAccessors)).toEqual(0);
});
it('returns correct value if isRespectRanges is true and color palette was provided', () => {
const accessors = {
metric: 'metric',
};
expect(getMinValue({ metric: 10 }, accessors, { rangeMin: 5 }, true)).toEqual(5);
expect(getMinValue({ metric: 2 }, accessors, { rangeMin: 5 }, true)).toEqual(2);
});
});
describe('getGoalValue', () => {
it('returns correct value', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import type { DatatableColumn, DatatableRow } from 'src/plugins/expressions';
import { getAccessorByDimension } from '../../../../../visualizations/common/utils';
import { Accessors, GaugeArguments } from '../../../common';
import { Accessors, GaugeArguments, CustomPaletteParams } from '../../../common';

export const getValueFromAccessor = (
accessor: string,
Expand Down Expand Up @@ -54,17 +54,30 @@ function getNiceNumber(localRange: number) {
return niceFraction * Math.pow(10, exponent);
}

export const getMaxValue = (row?: DatatableRow, accessors?: Accessors): number => {
export const getMaxValue = (
row?: DatatableRow,
accessors?: Accessors,
paletteParams?: CustomPaletteParams,
isRespectRanges?: boolean
): number => {
const FALLBACK_VALUE = 100;
const currentValue = accessors?.max ? getValueFromAccessor(accessors.max, row) : undefined;
if (currentValue !== undefined && currentValue !== null) {
return currentValue;
}

if (isRespectRanges && paletteParams?.rangeMax) {
const metricValue = accessors?.metric ? getValueFromAccessor(accessors.metric, row) : undefined;
return !metricValue || metricValue < paletteParams?.rangeMax
? paletteParams?.rangeMax
: metricValue;
}

if (row && accessors) {
const { metric, goal } = accessors;
const metricValue = metric && row[metric];
const goalValue = goal && row[goal];
const minValue = getMinValue(row, accessors);
const minValue = getMinValue(row, accessors, paletteParams, isRespectRanges);
if (metricValue != null) {
const numberValues = [minValue, goalValue, metricValue].filter((v) => typeof v === 'number');
const maxValue = Math.max(...numberValues);
Expand All @@ -74,11 +87,24 @@ export const getMaxValue = (row?: DatatableRow, accessors?: Accessors): number =
return FALLBACK_VALUE;
};

export const getMinValue = (row?: DatatableRow, accessors?: Accessors) => {
export const getMinValue = (
row?: DatatableRow,
accessors?: Accessors,
paletteParams?: CustomPaletteParams,
isRespectRanges?: boolean
) => {
const currentValue = accessors?.min ? getValueFromAccessor(accessors.min, row) : undefined;
if (currentValue !== undefined && currentValue !== null) {
return currentValue;
}

if (isRespectRanges && paletteParams?.rangeMin) {
const metricValue = accessors?.metric ? getValueFromAccessor(accessors.metric, row) : undefined;
return !metricValue || metricValue > paletteParams?.rangeMin
? paletteParams?.rangeMin
: metricValue;
}

const FALLBACK_VALUE = 0;
if (row && accessors) {
const { metric, max } = accessors;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/plugins/vis_types/gauge/public/to_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const toExpressionAst: VisToExpressionAst<GaugeVisParams> = (vis, params)
centralMajorMode,
...(centralMajorMode === 'custom' ? { labelMinor: style.subText } : {}),
percentageMode,
respectRanges: true,
commonLabel: schemas.metric?.[0]?.label,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ export const AllCasesList = React.memo<AllCasesListProps>(
}}
setFilterRefetch={setFilterRefetch}
hiddenStatuses={hiddenStatuses}
displayCreateCaseButton={isSelectorView}
onCreateCasePressed={onRowClick}
/>
<CasesTable
columns={columns}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,46 @@ describe('CasesTableFilters ', () => {

expect(onFilterChanged).toBeCalledWith({ owner: [SECURITY_SOLUTION_OWNER] });
});

describe('create case button', () => {
it('should not render the create case button when displayCreateCaseButton and onCreateCasePressed are not passed', () => {
const wrapper = mount(
<TestProviders>
<CasesTableFilters {...props} />
</TestProviders>
);
expect(wrapper.find(`[data-test-subj="cases-table-add-case-filter-bar"]`).length).toBe(0);
});

it('should render the create case button when displayCreateCaseButton and onCreateCasePressed are passed', () => {
const onCreateCasePressed = jest.fn();
const wrapper = mount(
<TestProviders>
<CasesTableFilters
{...props}
displayCreateCaseButton={true}
onCreateCasePressed={onCreateCasePressed}
/>
</TestProviders>
);
expect(wrapper.find(`[data-test-subj="cases-table-add-case-filter-bar"]`)).toBeTruthy();
});

it('should call the onCreateCasePressed when create case is clicked', () => {
const onCreateCasePressed = jest.fn();
const wrapper = mount(
<TestProviders>
<CasesTableFilters
{...props}
displayCreateCaseButton={true}
onCreateCasePressed={onCreateCasePressed}
/>
</TestProviders>
);
wrapper.find(`[data-test-subj="cases-table-add-case-filter-bar"]`).first().simulate('click');
wrapper.update();
// NOTE: intentionally checking no arguments are passed
expect(onCreateCasePressed).toHaveBeenCalledWith();
});
});
});
26 changes: 24 additions & 2 deletions x-pack/plugins/cases/public/components/all_cases/table_filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React, { useCallback, useEffect, useState, useMemo } from 'react';
import { isEqual } from 'lodash/fp';
import styled from 'styled-components';
import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiFilterGroup } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiFilterGroup, EuiButton } from '@elastic/eui';

import { StatusAll, CaseStatusWithAllStatus } from '../../../common/ui/types';
import { CaseStatuses } from '../../../common/api';
Expand All @@ -17,8 +17,8 @@ import { useGetTags } from '../../containers/use_get_tags';
import { useGetReporters } from '../../containers/use_get_reporters';
import { FilterPopover } from '../filter_popover';
import { StatusFilter } from './status_filter';

import * as i18n from './translations';

interface CasesTableFiltersProps {
countClosedCases: number | null;
countInProgressCases: number | null;
Expand All @@ -28,6 +28,8 @@ interface CasesTableFiltersProps {
setFilterRefetch: (val: () => void) => void;
hiddenStatuses?: CaseStatusWithAllStatus[];
availableSolutions: string[];
displayCreateCaseButton?: boolean;
onCreateCasePressed?: () => void;
}

// Fix the width of the status dropdown to prevent hiding long text items
Expand Down Expand Up @@ -61,6 +63,8 @@ const CasesTableFiltersComponent = ({
setFilterRefetch,
hiddenStatuses,
availableSolutions,
displayCreateCaseButton,
onCreateCasePressed,
}: CasesTableFiltersProps) => {
const [selectedReporters, setSelectedReporters] = useState(
initial.reporters.map((r) => r.full_name ?? r.username ?? '')
Expand Down Expand Up @@ -157,6 +161,12 @@ const CasesTableFiltersComponent = ({
[countClosedCases, countInProgressCases, countOpenCases]
);

const handleOnCreateCasePressed = useCallback(() => {
if (onCreateCasePressed) {
onCreateCasePressed();
}
}, [onCreateCasePressed]);

return (
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<EuiFlexItem>
Expand Down Expand Up @@ -207,6 +217,18 @@ const CasesTableFiltersComponent = ({
)}
</EuiFilterGroup>
</EuiFlexItem>
{displayCreateCaseButton && onCreateCasePressed ? (
<EuiFlexItem grow={false}>
<EuiButton
fill
onClick={handleOnCreateCasePressed}
iconType="plusInCircle"
data-test-subj="cases-table-add-case-filter-bar"
>
{i18n.CREATE_CASE_TITLE}
</EuiButton>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
);
};
Expand Down
Loading

0 comments on commit f0b8602

Please sign in to comment.