Skip to content

Commit

Permalink
Merge branch 'main' into ml-transform-reset
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Feb 1, 2022
2 parents 53a349b + 41e756c commit 591e8ef
Show file tree
Hide file tree
Showing 34 changed files with 601 additions and 94 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 @@ -33,6 +33,8 @@ describe('interpreter/functions#heatmap', () => {
isCellLabelVisible: true,
isYAxisLabelVisible: true,
isXAxisLabelVisible: true,
isYAxisTitleVisible: true,
isXAxisTitleVisible: true,
type: EXPRESSION_HEATMAP_GRID_NAME,
},
palette: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,39 @@ export const heatmapGridConfig: ExpressionFunctionDefinition<
defaultMessage: 'Specifies whether or not the Y-axis labels are visible.',
}),
},
isYAxisTitleVisible: {
types: ['boolean'],
help: i18n.translate('expressionHeatmap.function.args.grid.isYAxisTitleVisible.help', {
defaultMessage: 'Specifies whether or not the Y-axis title is visible.',
}),
},
yTitle: {
types: ['string'],
help: i18n.translate('expressionHeatmap.function.args.grid.yTitle.help', {
defaultMessage: 'Specifies the title of the y axis',
}),
required: false,
},
// X-axis
isXAxisLabelVisible: {
types: ['boolean'],
help: i18n.translate('expressionHeatmap.function.args.grid.isXAxisLabelVisible.help', {
defaultMessage: 'Specifies whether or not the X-axis labels are visible.',
}),
},
isXAxisTitleVisible: {
types: ['boolean'],
help: i18n.translate('expressionHeatmap.function.args.grid.isXAxisTitleVisible.help', {
defaultMessage: 'Specifies whether or not the X-axis title is visible.',
}),
},
xTitle: {
types: ['string'],
help: i18n.translate('expressionHeatmap.function.args.grid.xTitle.help', {
defaultMessage: 'Specifies the title of the x axis',
}),
required: false,
},
},
fn(input, args) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ export interface HeatmapGridConfig {
isCellLabelVisible: boolean;
// Y-axis
isYAxisLabelVisible: boolean;
isYAxisTitleVisible: boolean;
yTitle?: string;
// X-axis
isXAxisLabelVisible: boolean;
isXAxisTitleVisible: boolean;
xTitle?: string;
}

export type HeatmapGridConfigResult = HeatmapGridConfig & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const args: HeatmapArguments = {
isCellLabelVisible: true,
isYAxisLabelVisible: true,
isXAxisLabelVisible: true,
isYAxisTitleVisible: true,
isXAxisTitleVisible: true,
type: 'heatmap_grid',
},
palette: {
Expand All @@ -59,16 +61,18 @@ const args: HeatmapArguments = {
highlightInHover: false,
xAccessor: 'col-1-2',
valueAccessor: 'col-0-1',
yAccessor: 'col-2-3',
};
const data: Datatable = {
type: 'datatable',
rows: [
{ 'col-0-1': 0, 'col-1-2': 'a' },
{ 'col-0-1': 148, 'col-1-2': 'b' },
{ 'col-0-1': 0, 'col-1-2': 'a', 'col-2-3': 'd' },
{ 'col-0-1': 148, 'col-1-2': 'b', 'col-2-3': 'c' },
],
columns: [
{ id: 'col-0-1', name: 'Count', meta: { type: 'number' } },
{ id: 'col-1-2', name: 'Dest', meta: { type: 'string' } },
{ id: 'col-2-3', name: 'Test', meta: { type: 'string' } },
],
};

Expand Down Expand Up @@ -163,6 +167,25 @@ describe('HeatmapComponent', function () {
});
});

it('renders the axis titles', () => {
const component = shallowWithIntl(<HeatmapComponent {...wrapperProps} />);
expect(component.find(Heatmap).prop('xAxisTitle')).toEqual('Dest');
expect(component.find(Heatmap).prop('yAxisTitle')).toEqual('Test');
});

it('renders custom axis titles if given', () => {
const newProps = {
...wrapperProps,
args: {
...wrapperProps.args,
gridConfig: { ...wrapperProps.args.gridConfig, xTitle: 'test1', yTitle: 'test2' },
},
} as unknown as HeatmapRenderProps;
const component = shallowWithIntl(<HeatmapComponent {...newProps} />);
expect(component.find(Heatmap).prop('xAxisTitle')).toEqual('test1');
expect(component.find(Heatmap).prop('yAxisTitle')).toEqual('test2');
});

it('hides the legend if the legend isVisible args is false', async () => {
const newProps = {
...wrapperProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,9 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
},
};

const xAxisTitle = args.gridConfig.xTitle ?? xAxisColumn?.name;
const yAxisTitle = args.gridConfig.yTitle ?? yAxisColumn?.name;

return (
<>
{showLegend !== undefined && (
Expand Down Expand Up @@ -487,6 +490,8 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
xSortPredicate={xAxisColumn ? getSortPredicate(xAxisColumn) : 'dataIndex'}
xAxisLabelName={xAxisColumn?.name}
yAxisLabelName={yAxisColumn?.name}
xAxisTitle={args.gridConfig.isXAxisTitleVisible ? xAxisTitle : undefined}
yAxisTitle={args.gridConfig.isYAxisTitleVisible ? yAxisTitle : undefined}
xAxisLabelFormatter={(v) => `${xValuesFormatter.convert(v) ?? ''}`}
yAxisLabelFormatter={
yAxisColumn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,11 @@ class DashboardGridUi extends React.Component<DashboardGridProps, State> {
}
});

const dashboardPanels = _.map(panelsInOrder, ({ explicitInput, type }) => (
const dashboardPanels = _.map(panelsInOrder, ({ explicitInput, type }, index) => (
<DashboardGridItem
id={explicitInput.id}
key={explicitInput.id}
id={explicitInput.id}
index={index + 1}
type={type}
container={container}
PanelComponent={kibana.services.embeddable.EmbeddablePanel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type DivProps = Pick<React.HTMLAttributes<HTMLDivElement>, 'className' | 'style'

interface Props extends PanelProps, DivProps {
id: DashboardPanelState['explicitInput']['id'];
index?: number;
type: DashboardPanelState['type'];
container: DashboardContainer;
focusedPanelId?: string;
Expand All @@ -35,6 +36,7 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
expandedPanelId,
focusedPanelId,
id,
index,
PanelComponent,
type,
isRenderable = true,
Expand Down Expand Up @@ -72,6 +74,7 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
// This key is used to force rerendering on embeddable type change while the id remains the same
key={type}
embeddableId={id}
index={index}
{...{ container, PanelComponent }}
/>
{children}
Expand Down
26 changes: 26 additions & 0 deletions src/plugins/discover/public/__mocks__/local_storage_mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export class LocalStorageMock {
private store: Record<string, unknown>;
constructor(defaultStore: Record<string, unknown>) {
this.store = defaultStore;
}
clear() {
this.store = {};
}
get(key: string) {
return this.store[key] || null;
}
set(key: string, value: unknown) {
this.store[key] = String(value);
}
remove(key: string) {
delete this.store[key];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.dscDocumentExplorerCallout {
.euiCallOutHeader__title {
width: 100%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useCallback, useState } from 'react';
import './document_explorer_callout.scss';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiButton, EuiButtonIcon, EuiCallOut, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { useDiscoverServices } from '../../../../utils/use_discover_services';
import { DOC_TABLE_LEGACY } from '../../../../../common';
import { Storage } from '../../../../../../kibana_utils/public';

export const CALLOUT_STATE_KEY = 'discover:docExplorerCalloutClosed';

const getStoredCalloutState = (storage: Storage): boolean => {
const calloutClosed = storage.get(CALLOUT_STATE_KEY);
return Boolean(calloutClosed);
};
const updateStoredCalloutState = (newState: boolean, storage: Storage) => {
storage.set(CALLOUT_STATE_KEY, newState);
};

export const DocumentExplorerCallout = () => {
const { storage, capabilities, addBasePath } = useDiscoverServices();
const [calloutClosed, setCalloutClosed] = useState(getStoredCalloutState(storage));

const onCloseCallout = useCallback(() => {
updateStoredCalloutState(true, storage);
setCalloutClosed(true);
}, [storage]);

if (calloutClosed || !capabilities.advancedSettings.save) {
return null;
}

return (
<EuiCallOut
className="dscDocumentExplorerCallout"
title={<CalloutTitle onCloseCallout={onCloseCallout} />}
iconType="search"
>
<p>
<FormattedMessage
id="discover.docExplorerCallout.bodyMessage"
defaultMessage="Quickly sort, select, and compare data, resize columns, and view documents in fullscreen with the Document Explorer."
/>
</p>
<p>
<EuiButton
iconType="tableDensityNormal"
size="s"
href={addBasePath(`/app/management/kibana/settings?query=${DOC_TABLE_LEGACY}`)}
>
<FormattedMessage
id="discover.docExplorerCallout.tryDocumentExplorer"
defaultMessage="Try Document Explorer"
/>
</EuiButton>
</p>
</EuiCallOut>
);
};

function CalloutTitle({ onCloseCallout }: { onCloseCallout: () => void }) {
return (
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="none" responsive={false}>
<EuiFlexItem grow={false}>
<FormattedMessage
id="discover.docExplorerCallout.headerMessage"
defaultMessage="A better way to explore"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon
aria-label={i18n.translate('discover.docExplorerCallout.closeButtonAriaLabel', {
defaultMessage: 'Close',
})}
onClick={onCloseCallout}
type="button"
iconType="cross"
/>
</EuiFlexItem>
</EuiFlexGroup>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { mountWithIntl } from '@kbn/test/jest';
import { KibanaContextProvider } from '../../../../../../kibana_react/public';
import { CALLOUT_STATE_KEY, DocumentExplorerCallout } from './document_explorer_callout';
import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock';
import { DiscoverServices } from '../../../../build_services';

const defaultServices = {
addBasePath: () => '',
capabilities: { advancedSettings: { save: true } },
storage: new LocalStorageMock({ [CALLOUT_STATE_KEY]: false }),
} as unknown as DiscoverServices;

const mount = (services: DiscoverServices) => {
return mountWithIntl(
<KibanaContextProvider services={services}>
<DocumentExplorerCallout />
</KibanaContextProvider>
);
};

describe('Document Explorer callout', () => {
it('should render callout', () => {
const result = mount(defaultServices);

expect(result.find('.dscDocumentExplorerCallout').exists()).toBeTruthy();
});

it('should not render callout for user without permissions', () => {
const services = {
...defaultServices,
capabilities: { advancedSettings: { save: false } },
} as unknown as DiscoverServices;
const result = mount(services);

expect(result.find('.dscDocumentExplorerCallout').exists()).toBeFalsy();
});

it('should not render callout of it was closed', () => {
const services = {
...defaultServices,
storage: new LocalStorageMock({ [CALLOUT_STATE_KEY]: true }),
} as unknown as DiscoverServices;
const result = mount(services);

expect(result.find('.dscDocumentExplorerCallout').exists()).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export { DocumentExplorerCallout } from './document_explorer_callout';
Loading

0 comments on commit 591e8ef

Please sign in to comment.