Skip to content

Commit

Permalink
<ListManageDrilldowns/>
Browse files Browse the repository at this point in the history
  • Loading branch information
Dosant committed Mar 5, 2020
1 parent 5e71093 commit 765f962
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const txtCreateDrilldown = i18n.translate(
'xpack.drilldowns.components.ListManageDrilldowns.createDrilldownButtonLabel',
{
defaultMessage: 'Create new',
}
);

export const txtEditDrilldown = i18n.translate(
'xpack.drilldowns.components.ListManageDrilldowns.editDrilldownButtonLabel',
{
defaultMessage: 'Edit',
}
);

export const txtDeleteDrilldowns = (count: number) =>
i18n.translate('xpack.drilldowns.components.ListManageDrilldowns.deleteDrilldownsButtonLabel', {
defaultMessage: 'Delete ({count})',
values: {
count,
},
});

export const txtSelectDrilldown = i18n.translate(
'xpack.drilldowns.components.ListManageDrilldowns.selectThisDrilldownCheckboxLabel',
{
defaultMessage: 'Select this drilldown',
}
);
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 * from './list_manage_drilldowns';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 * as React from 'react';
import { storiesOf } from '@storybook/react';
import { ListManageDrilldowns } from './list_manage_drilldowns';
import { drilldowns } from './test_data';

storiesOf('components/ListManageDrilldowns', module).add('default', () => (
<ListManageDrilldowns drilldowns={drilldowns} />
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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 React from 'react';
import { cleanup, fireEvent, render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect'; // TODO: this should be global
import { drilldowns } from './test_data';
import { ListManageDrilldowns, TEST_SUBJ_DRILLDOWN_ITEM } from './list_manage_drilldowns';

// TODO: for some reason global cleanup from RTL doesn't work
// afterEach is not available for it globally during setup
afterEach(cleanup);

test('Render list of drilldowns', () => {
const screen = render(<ListManageDrilldowns drilldowns={drilldowns} />);
expect(screen.getAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(drilldowns.length);
});

test('Emit onEdit() when clicking on edit drilldown', () => {
const fn = jest.fn();
const screen = render(<ListManageDrilldowns drilldowns={drilldowns} onEdit={fn} />);

const editButtons = screen.getAllByText('Edit');
expect(editButtons).toHaveLength(drilldowns.length);
fireEvent.click(editButtons[1]);
expect(fn).toBeCalledWith(drilldowns[1].id);
});

test('Emit onCreate() when clicking on create drilldown', () => {
const fn = jest.fn();
const screen = render(<ListManageDrilldowns drilldowns={drilldowns} onCreate={fn} />);
fireEvent.click(screen.getByText('Create new'));
expect(fn).toBeCalled();
});

test('Delete button is not visible when non is selected', () => {
const fn = jest.fn();
const screen = render(<ListManageDrilldowns drilldowns={drilldowns} onCreate={fn} />);
expect(screen.queryByText(/Delete/i)).not.toBeInTheDocument();
expect(screen.queryByText(/Create/i)).toBeInTheDocument();
});

test('Can delete drilldowns', () => {
const fn = jest.fn();
const screen = render(<ListManageDrilldowns drilldowns={drilldowns} onDelete={fn} />);

const checkboxes = screen.getAllByLabelText(/Select this drilldown/i);
expect(checkboxes).toHaveLength(3);

fireEvent.click(checkboxes[1]);
fireEvent.click(checkboxes[2]);

expect(screen.queryByText(/Create/i)).not.toBeInTheDocument();

fireEvent.click(screen.getByText(/Delete \(2\)/i));

expect(fn).toBeCalledWith([drilldowns[1].id, drilldowns[2].id]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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 {
EuiBasicTable,
EuiBasicTableColumn,
EuiButton,
EuiButtonEmpty,
EuiSpacer,
} from '@elastic/eui';
import React, { useState } from 'react';
import {
txtEditDrilldown,
txtCreateDrilldown,
txtDeleteDrilldowns,
txtSelectDrilldown,
} from './i18n';

// TODO: interface is temporary
export interface DrilldownListItem {
id: string;
actionTypeDisplayName: string;
name: string;
}

export interface ListManageDrilldownsProps {
drilldowns: DrilldownListItem[];

onEdit?: (id: string) => void;
onCreate?: () => void;
onDelete?: (ids: string[]) => void;
}

const noop = () => {};

export const TEST_SUBJ_DRILLDOWN_ITEM = 'list-manage-drilldowns-item';

export function ListManageDrilldowns({
drilldowns,
onEdit = noop,
onCreate = noop,
onDelete = noop,
}: ListManageDrilldownsProps) {
const [selectedDrilldowns, setSelectedDrilldowns] = useState<string[]>([]);

const columns: Array<EuiBasicTableColumn<DrilldownListItem>> = [
{
field: 'name',
name: 'Name',
truncateText: true,
},
{
field: 'actionTypeDisplayName',
name: 'Action',
truncateText: true,
},
{
render: (drilldown: DrilldownListItem) => (
<EuiButtonEmpty size="xs" onClick={() => onEdit(drilldown.id)}>
{txtEditDrilldown}
</EuiButtonEmpty>
),
},
];

return (
<>
<EuiBasicTable
items={drilldowns}
itemId="id"
columns={columns}
isSelectable={true}
selection={{
onSelectionChange: selection => {
setSelectedDrilldowns(selection.map(drilldown => drilldown.id));
},
selectableMessage: () => txtSelectDrilldown,
}}
rowProps={{ 'data-test-subj': TEST_SUBJ_DRILLDOWN_ITEM }}
hasActions={true}
/>
<EuiSpacer />
{selectedDrilldowns.length === 0 ? (
<EuiButton fill onClick={() => onCreate()}>
{txtCreateDrilldown}
</EuiButton>
) : (
<EuiButton color="danger" fill onClick={() => onDelete(selectedDrilldowns)}>
{txtDeleteDrilldowns(selectedDrilldowns.length)}
</EuiButton>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 const drilldowns = [
{ id: '1', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 1' },
{ id: '2', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 2' },
{ id: '3', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 3' },
];

0 comments on commit 765f962

Please sign in to comment.