mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Canvas] Adds Label option for Dropdown Control (#88505)
* Adds Label option for Dropdown Control * Update Snapshots * Fix typecheck
This commit is contained in:
parent
609b5bf1b7
commit
8bd0e3217b
7 changed files with 83 additions and 26 deletions
|
@ -205,4 +205,34 @@ const stringTable: Datatable = {
|
|||
],
|
||||
};
|
||||
|
||||
export { emptyTable, testTable, stringTable };
|
||||
const relationalTable: Datatable = {
|
||||
type: 'datatable',
|
||||
columns: [
|
||||
{
|
||||
id: 'id',
|
||||
name: 'id',
|
||||
meta: { type: 'string' },
|
||||
},
|
||||
{
|
||||
id: 'name',
|
||||
name: 'name',
|
||||
meta: { type: 'string' },
|
||||
},
|
||||
],
|
||||
rows: [
|
||||
{
|
||||
id: '1',
|
||||
name: 'One',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Two',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Three',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { emptyTable, testTable, stringTable, relationalTable };
|
||||
|
|
|
@ -5,26 +5,27 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { uniq } from 'lodash';
|
||||
import { Datatable, Render, ExpressionFunctionDefinition } from '../../../types';
|
||||
import { uniqBy } from 'lodash';
|
||||
import { Datatable, ExpressionValueRender, ExpressionFunctionDefinition } from '../../../types';
|
||||
import { getFunctionHelp } from '../../../i18n';
|
||||
|
||||
interface Arguments {
|
||||
filterColumn: string;
|
||||
labelColumn: string;
|
||||
valueColumn: string;
|
||||
filterGroup: string;
|
||||
}
|
||||
|
||||
interface Return {
|
||||
column: string;
|
||||
choices: any;
|
||||
choices: Array<[string, string]>;
|
||||
}
|
||||
|
||||
export function dropdownControl(): ExpressionFunctionDefinition<
|
||||
'dropdownControl',
|
||||
Datatable,
|
||||
Arguments,
|
||||
Render<Return>
|
||||
ExpressionValueRender<Return>
|
||||
> {
|
||||
const { help, args: argHelp } = getFunctionHelp().dropdownControl;
|
||||
|
||||
|
@ -40,6 +41,11 @@ export function dropdownControl(): ExpressionFunctionDefinition<
|
|||
required: true,
|
||||
help: argHelp.filterColumn,
|
||||
},
|
||||
labelColumn: {
|
||||
types: ['string'],
|
||||
required: false,
|
||||
help: argHelp.labelColumn,
|
||||
},
|
||||
valueColumn: {
|
||||
types: ['string'],
|
||||
required: true,
|
||||
|
@ -50,15 +56,18 @@ export function dropdownControl(): ExpressionFunctionDefinition<
|
|||
help: argHelp.filterGroup,
|
||||
},
|
||||
},
|
||||
fn: (input, { valueColumn, filterColumn, filterGroup }) => {
|
||||
let choices = [];
|
||||
fn: (input, { valueColumn, filterColumn, filterGroup, labelColumn }) => {
|
||||
let choices: Array<[string, string]> = [];
|
||||
const labelCol = labelColumn || valueColumn;
|
||||
|
||||
const filteredRows = input.rows.filter(
|
||||
(row) => row[valueColumn] !== null && row[valueColumn] !== undefined
|
||||
);
|
||||
|
||||
if (filteredRows.length > 0) {
|
||||
choices = uniq(filteredRows.map((row) => row[valueColumn])).sort();
|
||||
choices = filteredRows.map((row) => [row[valueColumn], row[labelCol]]);
|
||||
|
||||
choices = uniqBy(choices, (choice) => choice[0]);
|
||||
}
|
||||
|
||||
const column = filterColumn || valueColumn;
|
||||
|
|
|
@ -5,16 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
// @ts-expect-error untyped local
|
||||
import { functionWrapper } from '../../../test_helpers/function_wrapper';
|
||||
import { testTable } from './__fixtures__/test_tables';
|
||||
import { testTable, relationalTable } from './__fixtures__/test_tables';
|
||||
import { dropdownControl } from './dropdownControl';
|
||||
|
||||
describe('dropdownControl', () => {
|
||||
const fn = functionWrapper(dropdownControl);
|
||||
const uniqueNames = testTable.rows.reduce(
|
||||
(unique, { name }) => (unique.includes(name) ? unique : unique.concat([name])),
|
||||
[]
|
||||
);
|
||||
|
||||
it('returns a render as dropdown_filter', () => {
|
||||
expect(fn(testTable, { filterColumn: 'name', valueColumn: 'name' })).toHaveProperty(
|
||||
|
@ -30,6 +27,11 @@ describe('dropdownControl', () => {
|
|||
describe('args', () => {
|
||||
describe('valueColumn', () => {
|
||||
it('populates dropdown choices with unique values in valueColumn', () => {
|
||||
const uniqueNames = testTable.rows.reduce<Array<[string, string]>>(
|
||||
(unique, { name }) =>
|
||||
unique.find(([value, label]) => value === name) ? unique : [...unique, [name, name]],
|
||||
[]
|
||||
);
|
||||
expect(fn(testTable, { valueColumn: 'name' }).value.choices).toEqual(uniqueNames);
|
||||
});
|
||||
|
||||
|
@ -38,6 +40,15 @@ describe('dropdownControl', () => {
|
|||
expect(fn(testTable, { valueColumn: '' }).value.choices).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('labelColumn', () => {
|
||||
it('populates dropdown choices with labels from label column', () => {
|
||||
const expectedChoices = relationalTable.rows.map((row) => [row.id, row.name]);
|
||||
expect(
|
||||
fn(relationalTable, { valueColumn: 'id', labelColumn: 'name' }).value.choices
|
||||
).toEqual(expectedChoices);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterColumn', () => {
|
|
@ -40,19 +40,19 @@ exports[`Storyshots renderers/DropdownFilter with choices 1`] = `
|
|||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item One"
|
||||
value="1"
|
||||
>
|
||||
Item One
|
||||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item Two"
|
||||
value="2"
|
||||
>
|
||||
Item Two
|
||||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item Three"
|
||||
value="3"
|
||||
>
|
||||
Item Three
|
||||
</option>
|
||||
|
@ -82,19 +82,19 @@ exports[`Storyshots renderers/DropdownFilter with choices and new value 1`] = `
|
|||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item One"
|
||||
value="1"
|
||||
>
|
||||
Item One
|
||||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item Two"
|
||||
value="2"
|
||||
>
|
||||
Item Two
|
||||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item Three"
|
||||
value="3"
|
||||
>
|
||||
Item Three
|
||||
</option>
|
||||
|
@ -124,19 +124,19 @@ exports[`Storyshots renderers/DropdownFilter with choices and value 1`] = `
|
|||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item One"
|
||||
value="1"
|
||||
>
|
||||
Item One
|
||||
</option>
|
||||
<option
|
||||
aria-selected={true}
|
||||
value="Item Two"
|
||||
aria-selected={false}
|
||||
value="2"
|
||||
>
|
||||
Item Two
|
||||
</option>
|
||||
<option
|
||||
aria-selected={false}
|
||||
value="Item Three"
|
||||
value="3"
|
||||
>
|
||||
Item Three
|
||||
</option>
|
||||
|
|
|
@ -10,7 +10,11 @@ import { storiesOf } from '@storybook/react';
|
|||
import React from 'react';
|
||||
import { DropdownFilter } from '../dropdown_filter';
|
||||
|
||||
const choices = ['Item One', 'Item Two', 'Item Three'];
|
||||
const choices: Array<[string, string]> = [
|
||||
['1', 'Item One'],
|
||||
['2', 'Item Two'],
|
||||
['3', 'Item Three'],
|
||||
];
|
||||
|
||||
storiesOf('renderers/DropdownFilter', module)
|
||||
.add('default', () => <DropdownFilter onChange={action('onChange')} commit={action('commit')} />)
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface Props {
|
|||
* A collection of choices to display in the dropdown
|
||||
* @default []
|
||||
*/
|
||||
choices?: string[];
|
||||
choices?: Array<[string, string]>;
|
||||
/**
|
||||
* Optional value for the component. If the value is not present in the
|
||||
* choices collection, it will be discarded.
|
||||
|
@ -38,7 +38,7 @@ export const DropdownFilter: FunctionComponent<Props> = ({
|
|||
let options = [
|
||||
{ value: '%%CANVAS_MATCH_ALL%%', text: `-- ${strings.getMatchAllOptionLabel()} --` },
|
||||
];
|
||||
options = options.concat(choices.map((choice) => ({ value: choice, text: choice })));
|
||||
options = options.concat(choices.map((choice) => ({ value: choice[0], text: choice[1] })));
|
||||
|
||||
const changeHandler = (e: FocusEvent<HTMLSelectElement> | ChangeEvent<HTMLSelectElement>) => {
|
||||
if (e && e.target) {
|
||||
|
|
|
@ -21,6 +21,9 @@ export const help: FunctionHelp<FunctionFactory<typeof dropdownControl>> = {
|
|||
defaultMessage: 'The column or field that you want to filter.',
|
||||
}
|
||||
),
|
||||
labelColumn: i18n.translate('xpack.canvas.functions.dropdownControl.args.labelColumnHelpText', {
|
||||
defaultMessage: 'The column or field to use as the label in the dropdown control',
|
||||
}),
|
||||
valueColumn: i18n.translate('xpack.canvas.functions.dropdownControl.args.valueColumnHelpText', {
|
||||
defaultMessage:
|
||||
'The column or field from which to extract the unique values for the dropdown control.',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue