[Graph] Only show explorable fields (#54101)
This commit is contained in:
parent
07278aba37
commit
51e07f27f2
|
@ -33,6 +33,7 @@ describe('field_manager', () => {
|
|||
selected: true,
|
||||
type: 'string',
|
||||
hopSize: 5,
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
name: 'field2',
|
||||
|
@ -42,6 +43,7 @@ describe('field_manager', () => {
|
|||
type: 'string',
|
||||
hopSize: 0,
|
||||
lastValidHopSize: 5,
|
||||
aggregatable: false,
|
||||
},
|
||||
{
|
||||
name: 'field3',
|
||||
|
@ -50,6 +52,16 @@ describe('field_manager', () => {
|
|||
selected: false,
|
||||
type: 'string',
|
||||
hopSize: 5,
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
name: 'field4',
|
||||
color: 'orange',
|
||||
icon: getSuitableIcon('field4'),
|
||||
selected: false,
|
||||
type: 'string',
|
||||
hopSize: 5,
|
||||
aggregatable: false,
|
||||
},
|
||||
])
|
||||
);
|
||||
|
@ -86,6 +98,17 @@ describe('field_manager', () => {
|
|||
).toEqual('field2');
|
||||
});
|
||||
|
||||
it('should show selected non-aggregatable fields in picker, but hide unselected ones', () => {
|
||||
expect(
|
||||
getInstance()
|
||||
.find(FieldPicker)
|
||||
.dive()
|
||||
.find(EuiSelectable)
|
||||
.prop('options')
|
||||
.map((option: { label: string }) => option.label)
|
||||
).toEqual(['field1', 'field2', 'field3']);
|
||||
});
|
||||
|
||||
it('should select fields from picker', () => {
|
||||
expect(
|
||||
getInstance()
|
||||
|
@ -130,6 +153,25 @@ describe('field_manager', () => {
|
|||
expect(getInstance().find(FieldEditor).length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should show remove non-aggregatable fields from picker after deselection', () => {
|
||||
act(() => {
|
||||
getInstance()
|
||||
.find(FieldEditor)
|
||||
.at(1)
|
||||
.dive()
|
||||
.find(EuiContextMenu)
|
||||
.prop('panels')![0].items![2].onClick!({} as any);
|
||||
});
|
||||
expect(
|
||||
getInstance()
|
||||
.find(FieldPicker)
|
||||
.dive()
|
||||
.find(EuiSelectable)
|
||||
.prop('options')
|
||||
.map((option: { label: string }) => option.label)
|
||||
).toEqual(['field1', 'field3']);
|
||||
});
|
||||
|
||||
it('should disable field', () => {
|
||||
const toggleItem = getInstance()
|
||||
.find(FieldEditor)
|
||||
|
|
|
@ -114,9 +114,26 @@ export function FieldPicker({
|
|||
function toOptions(
|
||||
fields: WorkspaceField[]
|
||||
): Array<{ label: string; checked?: 'on' | 'off'; prepend?: ReactNode }> {
|
||||
return fields.map(field => ({
|
||||
label: field.name,
|
||||
prepend: <FieldIcon type={field.type} size="m" useColor />,
|
||||
checked: field.selected ? 'on' : undefined,
|
||||
}));
|
||||
return (
|
||||
fields
|
||||
// don't show non-aggregatable fields, except for the case when they are already selected.
|
||||
// this is necessary to ensure backwards compatibility with existing workspaces that might
|
||||
// contain non-aggregatable fields.
|
||||
.filter(field => isExplorable(field) || field.selected)
|
||||
.map(field => ({
|
||||
label: field.name,
|
||||
prepend: <FieldIcon type={field.type} size="m" useColor />,
|
||||
checked: field.selected ? 'on' : undefined,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
const explorableTypes = ['string', 'number', 'date', 'ip', 'boolean'];
|
||||
|
||||
function isExplorable(field: WorkspaceField) {
|
||||
if (!field.aggregatable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return explorableTypes.includes(field.type);
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ describe('settings', () => {
|
|||
code: '1',
|
||||
label: 'test',
|
||||
},
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
selected: false,
|
||||
|
@ -123,6 +124,7 @@ describe('settings', () => {
|
|||
code: '1',
|
||||
label: 'test',
|
||||
},
|
||||
aggregatable: true,
|
||||
},
|
||||
])
|
||||
);
|
||||
|
|
|
@ -13,8 +13,24 @@ describe('fetch_top_nodes', () => {
|
|||
it('should build terms agg', async () => {
|
||||
const postMock = jest.fn(() => Promise.resolve({ resp: {} }));
|
||||
await fetchTopNodes(postMock as any, 'test', [
|
||||
{ color: '', hopSize: 5, icon, name: 'field1', selected: false, type: 'string' },
|
||||
{ color: '', hopSize: 5, icon, name: 'field2', selected: false, type: 'string' },
|
||||
{
|
||||
color: '',
|
||||
hopSize: 5,
|
||||
icon,
|
||||
name: 'field1',
|
||||
selected: false,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
color: '',
|
||||
hopSize: 5,
|
||||
icon,
|
||||
name: 'field2',
|
||||
selected: false,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
]);
|
||||
expect(postMock).toHaveBeenCalledWith('../api/graph/searchProxy', {
|
||||
body: JSON.stringify({
|
||||
|
@ -65,8 +81,24 @@ describe('fetch_top_nodes', () => {
|
|||
})
|
||||
);
|
||||
const result = await fetchTopNodes(postMock as any, 'test', [
|
||||
{ color: 'red', hopSize: 5, icon, name: 'field1', selected: false, type: 'string' },
|
||||
{ color: 'blue', hopSize: 5, icon, name: 'field2', selected: false, type: 'string' },
|
||||
{
|
||||
color: 'red',
|
||||
hopSize: 5,
|
||||
icon,
|
||||
name: 'field1',
|
||||
selected: false,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
color: 'blue',
|
||||
hopSize: 5,
|
||||
icon,
|
||||
name: 'field2',
|
||||
selected: false,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
]);
|
||||
expect(result.length).toEqual(4);
|
||||
expect(result[0]).toEqual({
|
||||
|
|
|
@ -119,9 +119,9 @@ describe('deserialize', () => {
|
|||
savedWorkspace,
|
||||
{
|
||||
getNonScriptedFields: () => [
|
||||
{ name: 'field1', type: 'string' },
|
||||
{ name: 'field2', type: 'string' },
|
||||
{ name: 'field3', type: 'string' },
|
||||
{ name: 'field1', type: 'string', aggregatable: true },
|
||||
{ name: 'field2', type: 'string', aggregatable: true },
|
||||
{ name: 'field3', type: 'string', aggregatable: true },
|
||||
],
|
||||
} as IndexPattern,
|
||||
workspace
|
||||
|
@ -140,6 +140,7 @@ describe('deserialize', () => {
|
|||
expect(allFields).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"color": "black",
|
||||
"hopSize": undefined,
|
||||
"icon": undefined,
|
||||
|
@ -149,6 +150,7 @@ describe('deserialize', () => {
|
|||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"color": "black",
|
||||
"hopSize": undefined,
|
||||
"icon": undefined,
|
||||
|
@ -158,6 +160,7 @@ describe('deserialize', () => {
|
|||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"color": "#CE0060",
|
||||
"hopSize": 5,
|
||||
"icon": Object {
|
||||
|
|
|
@ -89,6 +89,7 @@ export function mapFields(indexPattern: IndexPattern): WorkspaceField[] {
|
|||
color: colorChoices[index % colorChoices.length],
|
||||
selected: false,
|
||||
type: field.type,
|
||||
aggregatable: Boolean(field.aggregatable),
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
if (a.name < b.name) {
|
||||
|
|
|
@ -41,6 +41,7 @@ describe('serialize', () => {
|
|||
name: 'field1',
|
||||
selected: true,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
color: 'black',
|
||||
|
@ -48,6 +49,7 @@ describe('serialize', () => {
|
|||
name: 'field2',
|
||||
selected: true,
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
},
|
||||
],
|
||||
selectedIndex: {
|
||||
|
|
|
@ -25,6 +25,7 @@ export interface WorkspaceField {
|
|||
icon: FontawesomeIcon;
|
||||
selected: boolean;
|
||||
type: string;
|
||||
aggregatable: boolean;
|
||||
}
|
||||
|
||||
export interface AdvancedSettings {
|
||||
|
|
|
@ -37,7 +37,7 @@ export interface SerializedUrlTemplate extends Omit<UrlTemplate, 'encoder' | 'ic
|
|||
encoderID: string;
|
||||
iconClass?: string;
|
||||
}
|
||||
export interface SerializedField extends Omit<WorkspaceField, 'icon' | 'type'> {
|
||||
export interface SerializedField extends Omit<WorkspaceField, 'icon' | 'type' | 'aggregatable'> {
|
||||
iconClass: string;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue