Skip to content

Commit

Permalink
Merge branch 'main' into visualize-no-data-page
Browse files Browse the repository at this point in the history
  • Loading branch information
stratoula authored May 17, 2022
2 parents c5c5257 + af3c090 commit cea6c6b
Show file tree
Hide file tree
Showing 68 changed files with 2,485 additions and 889 deletions.
1 change: 1 addition & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ disabled:
- x-pack/test/security_solution_cypress/upgrade_config.ts
- x-pack/test/security_solution_cypress/visual_config.ts
- x-pack/test/functional_enterprise_search/with_host_configured.config.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config_open.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config.ts

Expand Down

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 @@ -72,6 +72,7 @@ describe('MetricVisComponent', function () {
visData,
renderComplete: jest.fn(),
fireEvent: jest.fn(),
filterable: [true],
...propOverrides,
};

Expand All @@ -88,6 +89,7 @@ describe('MetricVisComponent', function () {

it('should render correct structure for multi-value metrics', function () {
const component = getComponent({
filterable: [true, false],
visData: {
type: 'datatable',
columns: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import './metric.scss';
export interface MetricVisComponentProps {
visParams: Pick<VisParams, 'metric' | 'dimensions'>;
visData: Datatable;
filterable: boolean[];
fireEvent: (event: any) => void;
renderComplete: () => void;
}
Expand Down Expand Up @@ -127,6 +128,7 @@ class MetricVisComponent extends Component<MetricVisComponentProps> {
};

private renderMetric = (metric: MetricOptions, index: number) => {
const hasBuckets = this.props.visParams.dimensions.bucket !== undefined;
const MetricComponent = this.props.visParams.metric.autoScale
? AutoScaleMetricVisValue
: MetricVisValue;
Expand All @@ -147,7 +149,11 @@ class MetricVisComponent extends Component<MetricVisComponentProps> {
key={index}
metric={metric}
style={this.props.visParams.metric.style}
onFilter={() => this.filterColumn(metric.rowIndex, metric.colIndex)}
onFilter={
hasBuckets || this.props.filterable[index]
? () => this.filterColumn(metric.rowIndex, metric.colIndex)
: undefined
}
autoScale={this.props.visParams.metric.autoScale}
colorFullBackground={this.props.visParams.metric.colorFullBackground}
labelConfig={this.props.visParams.metric.labels}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,48 @@ import { render, unmountComponentAtNode } from 'react-dom';

import { ThemeServiceStart } from '@kbn/core/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
import { EXPRESSION_METRIC_NAME, MetricVisRenderConfig } from '../../common';
import {
ExpressionValueVisDimension,
VisualizationContainer,
} from '@kbn/visualizations-plugin/public';
import {
ExpressionRenderDefinition,
IInterpreterRenderHandlers,
} from '@kbn/expressions-plugin/common/expression_renderers';
import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
import { Datatable } from '@kbn/expressions-plugin';
import { EXPRESSION_METRIC_NAME, MetricVisRenderConfig, VisParams } from '../../common';

// @ts-ignore
const MetricVisComponent = lazy(() => import('../components/metric_component'));

async function metricFilterable(
dimensions: VisParams['dimensions'],
table: Datatable,
handlers: IInterpreterRenderHandlers
) {
return Promise.all(
dimensions.metrics.map(async (metric: string | ExpressionValueVisDimension) => {
const column = getColumnByAccessor(metric, table.columns);
const colIndex = table.columns.indexOf(column!);
return Boolean(
await handlers.hasCompatibleActions?.({
name: 'filter',
data: {
data: [
{
table,
column: colIndex,
row: 0,
},
],
},
})
);
})
);
}

export const getMetricVisRenderer = (
theme: ThemeServiceStart
): (() => ExpressionRenderDefinition<MetricVisRenderConfig>) => {
Expand All @@ -30,6 +65,8 @@ export const getMetricVisRenderer = (
unmountComponentAtNode(domNode);
});

const filterable = await metricFilterable(visConfig.dimensions, visData, handlers);

render(
<KibanaThemeProvider theme$={theme.theme$}>
<VisualizationContainer
Expand All @@ -43,6 +80,7 @@ export const getMetricVisRenderer = (
visParams={visConfig}
renderComplete={handlers.done}
fireEvent={handlers.event}
filterable={filterable}
/>
</VisualizationContainer>
</KibanaThemeProvider>,
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/data/public/actions/value_click_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export function createValueClickAction(
type: ACTION_VALUE_CLICK,
id: ACTION_VALUE_CLICK,
shouldAutoExecute: async () => true,
isCompatible: async (context: ValueClickContext) => {
const filters = await createFiltersFromValueClickAction(context.data);
return filters.length > 0;
},
execute: async (context: ValueClickActionContext) => {
try {
const filters: Filter[] = await createFiltersFromValueClickAction(context.data);
Expand Down
6 changes: 4 additions & 2 deletions src/plugins/ui_actions/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { CoreSetup, CoreStart } from '@kbn/core/public';
import { coreMock } from '@kbn/core/public/mocks';
import { UiActionsSetup, UiActionsStart } from '.';
import { Action, UiActionsSetup, UiActionsStart } from '.';
import { plugin as pluginInitializer } from '.';

export type Setup = jest.Mocked<UiActionsSetup>;
Expand Down Expand Up @@ -39,7 +39,9 @@ const createStartContract = (): Start => {
hasAction: jest.fn(),
getTrigger: jest.fn(),
getTriggerActions: jest.fn((id: string) => []),
getTriggerCompatibleActions: jest.fn(),
getTriggerCompatibleActions: jest.fn((triggerId: string, context: object) =>
Promise.resolve([] as Array<Action<object>>)
),
registerAction: jest.fn(),
registerTrigger: jest.fn(),
};
Expand Down
11 changes: 0 additions & 11 deletions test/functional/apps/visualize/group2/_metric_chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});

describe('with filters', function () {
it('should allow filtering without buckets', async function () {
let filterCount = 0;
await retry.try(async function tryingForTime() {
// click first metric bucket
await PageObjects.visEditor.clickMetricByIndex(0);
filterCount = await filterBar.getFilterCount();
});
await filterBar.removeAllFilters();
expect(filterCount).to.equal(1);
});

it('should allow filtering with buckets', async function () {
log.debug('Bucket = Split Group');
await PageObjects.visEditor.clickBucket('Split group');
Expand Down
41 changes: 39 additions & 2 deletions x-pack/plugins/actions/server/actions_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ beforeEach(() => {
};
actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -532,6 +533,7 @@ describe('create()', () => {

actionTypeRegistry = new ActionTypeRegistry(localActionTypeRegistryParams);
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -635,6 +637,7 @@ describe('get()', () => {

test('ensures user is authorised to get preconfigured type of action', async () => {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -693,6 +696,7 @@ describe('get()', () => {

test('throws when user is not authorised to get preconfigured of action', async () => {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -813,6 +817,7 @@ describe('get()', () => {

test('return predefined action with id', async () => {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -886,6 +891,7 @@ describe('getAll()', () => {
);

actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -1026,6 +1032,7 @@ describe('getAll()', () => {
);

actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -1106,6 +1113,7 @@ describe('getBulk()', () => {
);

actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -1240,6 +1248,7 @@ describe('getBulk()', () => {
);

actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -1297,6 +1306,7 @@ describe('getOAuthAccessToken()', () => {
requestBody: OAuthParams
): ReturnType<ActionsClient['getOAuthAccessToken']> {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand All @@ -1321,7 +1331,7 @@ describe('getOAuthAccessToken()', () => {
],
connectorTokenClient: connectorTokenClientMock.create(),
});
return actionsClient.getOAuthAccessToken(requestBody, logger, configurationUtilities);
return actionsClient.getOAuthAccessToken(requestBody, configurationUtilities);
}

describe('authorization', () => {
Expand Down Expand Up @@ -1583,7 +1593,6 @@ describe('delete()', () => {
test('ensures user is authorised to delete actions', async () => {
await actionsClient.delete({ id: '1' });
expect(authorization.ensureAuthorized).toHaveBeenCalledWith('delete');
expect(connectorTokenClient.deleteConnectorTokens).toHaveBeenCalledTimes(1);
});

test('throws when user is not authorised to create the type of action', async () => {
Expand All @@ -1597,6 +1606,19 @@ describe('delete()', () => {

expect(authorization.ensureAuthorized).toHaveBeenCalledWith('delete');
});

test(`deletes any existing authorization tokens`, async () => {
await actionsClient.delete({ id: '1' });
expect(connectorTokenClient.deleteConnectorTokens).toHaveBeenCalledTimes(1);
});

test(`failing to delete tokens logs error instead of throw`, async () => {
connectorTokenClient.deleteConnectorTokens.mockRejectedValueOnce(new Error('Fail'));
await expect(actionsClient.delete({ id: '1' })).resolves.toBeUndefined();
expect(logger.error).toHaveBeenCalledWith(
`Failed to delete auth tokens for connector "1" after delete: Fail`
);
});
});

describe('auditLogger', () => {
Expand Down Expand Up @@ -1703,6 +1725,19 @@ describe('update()', () => {

expect(authorization.ensureAuthorized).toHaveBeenCalledWith('update');
});

test(`deletes any existing authorization tokens`, async () => {
await updateOperation();
expect(connectorTokenClient.deleteConnectorTokens).toHaveBeenCalledTimes(1);
});

test(`failing to delete tokens logs error instead of throw`, async () => {
connectorTokenClient.deleteConnectorTokens.mockRejectedValueOnce(new Error('Fail'));
await expect(updateOperation()).resolves.toBeTruthy();
expect(logger.error).toHaveBeenCalledWith(
`Failed to delete auth tokens for connector "my-action" after update: Fail`
);
});
});

describe('auditLogger', () => {
Expand Down Expand Up @@ -2305,6 +2340,7 @@ describe('isActionTypeEnabled()', () => {
describe('isPreconfigured()', () => {
test('should return true if connector id is in list of preconfigured connectors', () => {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down Expand Up @@ -2341,6 +2377,7 @@ describe('isPreconfigured()', () => {

test('should return false if connector id is not in list of preconfigured connectors', () => {
actionsClient = new ActionsClient({
logger,
actionTypeRegistry,
unsecuredSavedObjectsClient,
scopedClusterClient,
Expand Down
Loading

0 comments on commit cea6c6b

Please sign in to comment.