[Discover] Always show unmapped fields (#91735) (#92070)

* [Discover] Always show unmapped fields

* Updating the functional test

* Remove unmapped switch toggle

* Some more code cleanup

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Maja Grubic 2021-02-22 10:09:12 +00:00 committed by GitHub
parent 7f054cbf55
commit 391b3a827f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 17 additions and 216 deletions

View file

@ -675,19 +675,10 @@ function discoverController($route, $scope, Promise) {
history.push('/');
};
const showUnmappedFieldsDefaultValue = $scope.useNewFieldsApi && !!$scope.opts.savedSearch.pre712;
let showUnmappedFields = showUnmappedFieldsDefaultValue;
const onChangeUnmappedFields = (value) => {
showUnmappedFields = value;
$scope.unmappedFieldsConfig.showUnmappedFields = value;
$scope.fetch();
};
const showUnmappedFields = $scope.useNewFieldsApi;
$scope.unmappedFieldsConfig = {
showUnmappedFieldsDefaultValue,
showUnmappedFields,
onChangeUnmappedFields,
};
$scope.updateDataSource = () => {

View file

@ -136,22 +136,4 @@ describe('DiscoverFieldSearch', () => {
popover = component.find(EuiPopover);
expect(popover.prop('isOpen')).toBe(false);
});
test('unmapped fields', () => {
const onChangeUnmappedFields = jest.fn();
const componentProps = {
...defaultProps,
showUnmappedFields: true,
useNewFieldsApi: false,
onChangeUnmappedFields,
};
const component = mountComponent(componentProps);
const btn = findTestSubject(component, 'toggleFieldFilterButton');
btn.simulate('click');
const unmappedFieldsSwitch = findTestSubject(component, 'unmappedFieldsSwitch');
act(() => {
unmappedFieldsSwitch.simulate('click');
});
expect(onChangeUnmappedFields).toHaveBeenCalledWith(false);
});
});

View file

@ -27,8 +27,6 @@ import {
EuiOutsideClickDetector,
EuiFilterButton,
EuiSpacer,
EuiIcon,
EuiToolTip,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
@ -37,7 +35,6 @@ export interface State {
aggregatable: string;
type: string;
missing: boolean;
unmappedFields: boolean;
[index: string]: string | boolean;
}
@ -61,31 +58,13 @@ export interface Props {
* use new fields api
*/
useNewFieldsApi?: boolean;
/**
* callback funtion to change the value of unmapped fields switch
* @param value new value to set
*/
onChangeUnmappedFields?: (value: boolean) => void;
/**
* should unmapped fields switch be rendered
*/
showUnmappedFields?: boolean;
}
/**
* Component is Discover's side bar to search of available fields
* Additionally there's a button displayed that allows the user to show/hide more filter fields
*/
export function DiscoverFieldSearch({
onChange,
value,
types,
useNewFieldsApi,
showUnmappedFields,
onChangeUnmappedFields,
}: Props) {
export function DiscoverFieldSearch({ onChange, value, types, useNewFieldsApi }: Props) {
const searchPlaceholder = i18n.translate('discover.fieldChooser.searchPlaceHolder', {
defaultMessage: 'Search field names',
});
@ -111,7 +90,6 @@ export function DiscoverFieldSearch({
aggregatable: 'any',
type: 'any',
missing: true,
unmappedFields: !!showUnmappedFields,
});
if (typeof value !== 'string') {
@ -181,14 +159,6 @@ export function DiscoverFieldSearch({
handleValueChange('missing', missingValue);
};
const handleUnmappedFieldsChange = (e: EuiSwitchEvent) => {
const unmappedFieldsValue = e.target.checked;
handleValueChange('unmappedFields', unmappedFieldsValue);
if (onChangeUnmappedFields) {
onChangeUnmappedFields(unmappedFieldsValue);
}
};
const buttonContent = (
<EuiFilterButton
aria-label={filterBtnAriaLabel}
@ -262,46 +232,19 @@ export function DiscoverFieldSearch({
};
const footer = () => {
if (!showUnmappedFields && useNewFieldsApi) {
if (useNewFieldsApi) {
return null;
}
return (
<EuiPopoverFooter>
{showUnmappedFields ? (
<EuiFlexGroup>
<EuiFlexItem component="span">
<EuiSwitch
label={i18n.translate('discover.fieldChooser.filter.showUnmappedFields', {
defaultMessage: 'Show unmapped fields',
})}
checked={values.unmappedFields}
onChange={handleUnmappedFieldsChange}
data-test-subj="unmappedFieldsSwitch"
/>
</EuiFlexItem>
<EuiFlexItem component="span" grow={false}>
<EuiToolTip
position="right"
content={i18n.translate('discover.fieldChooser.filter.unmappedFieldsWarning', {
defaultMessage:
'Unmapped fields will be deprecated and removed in a future release.',
})}
>
<EuiIcon type="alert" />
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
) : null}
{useNewFieldsApi ? null : (
<EuiSwitch
label={i18n.translate('discover.fieldChooser.filter.hideMissingFieldsLabel', {
defaultMessage: 'Hide missing fields',
})}
checked={values.missing}
onChange={handleMissingChange}
data-test-subj="missingSwitch"
/>
)}
<EuiSwitch
label={i18n.translate('discover.fieldChooser.filter.hideMissingFieldsLabel', {
defaultMessage: 'Hide missing fields',
})}
checked={values.missing}
onChange={handleMissingChange}
data-test-subj="missingSwitch"
/>
</EuiPopoverFooter>
);
};

View file

@ -205,8 +205,6 @@ export function DiscoverSidebar({
value={fieldFilter.name}
types={fieldTypes}
useNewFieldsApi={useNewFieldsApi}
onChangeUnmappedFields={unmappedFieldsConfig?.onChangeUnmappedFields}
showUnmappedFields={unmappedFieldsConfig?.showUnmappedFieldsDefaultValue}
/>
</form>
</EuiFlexItem>

View file

@ -137,9 +137,7 @@ describe('discover responsive sidebar', function () {
});
it('renders sidebar with unmapped fields config', function () {
const unmappedFieldsConfig = {
onChangeUnmappedFields: jest.fn(),
showUnmappedFields: false,
showUnmappedFieldsDefaultValue: false,
};
const componentProps = { ...props, unmappedFieldsConfig };
const component = mountWithIntl(<DiscoverSidebarResponsive {...componentProps} />);

View file

@ -113,24 +113,13 @@ export interface DiscoverSidebarResponsiveProps {
useNewFieldsApi?: boolean;
/**
* an object containing properties for proper handling of unmapped fields in the UI
* an object containing properties for proper handling of unmapped fields
*/
unmappedFieldsConfig?: {
/**
* callback function to change the value of `showUnmappedFields` flag
* @param value new value to set
*/
onChangeUnmappedFields: (value: boolean) => void;
/**
* determines whether to display unmapped fields
* configurable through the switch in the UI
*/
showUnmappedFields: boolean;
/**
* determines if we should display an option to toggle showUnmappedFields value in the first place
* this value is not configurable through the UI
*/
showUnmappedFieldsDefaultValue: boolean;
};
}

View file

@ -159,23 +159,12 @@ export interface DiscoverProps {
*/
timeRange?: { from: string; to: string };
/**
* An object containing properties for proper handling of unmapped fields in the UI
* An object containing properties for unmapped fields behavior
*/
unmappedFieldsConfig?: {
/**
* determines whether to display unmapped fields
* configurable through the switch in the UI
*/
showUnmappedFields: boolean;
/**
* determines if we should display an option to toggle showUnmappedFields value in the first place
* this value is not configurable through the UI
*/
showUnmappedFieldsDefaultValue: boolean;
/**
* callback function to change the value of `showUnmappedFields` flag
* @param value new value to set
*/
onChangeUnmappedFields: (value: boolean) => void;
};
}

View file

@ -291,7 +291,7 @@ export class SearchEmbeddable
const useNewFieldsApi = !this.services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE, false);
if (!this.searchScope) return;
const { searchSource, pre712 } = this.savedSearch;
const { searchSource } = this.savedSearch;
// Abort any in-progress requests
if (this.abortController) this.abortController.abort();
@ -308,10 +308,7 @@ export class SearchEmbeddable
);
if (useNewFieldsApi) {
searchSource.removeField('fieldsFromSource');
const fields: Record<string, string> = { field: '*' };
if (pre712) {
fields.include_unmapped = 'true';
}
const fields: Record<string, string> = { field: '*', include_unmapped: 'true' };
searchSource.setField('fields', [fields]);
} else {
searchSource.removeField('fields');

View file

@ -20,7 +20,6 @@ export function createSavedSearchClass(savedObjects: SavedObjectsStart) {
grid: 'object',
sort: 'keyword',
version: 'integer',
pre712: 'boolean',
};
// Order these fields to the top, the rest are alphabetical
public static fieldOrder = ['title', 'description'];
@ -42,7 +41,6 @@ export function createSavedSearchClass(savedObjects: SavedObjectsStart) {
grid: 'object',
sort: 'keyword',
version: 'integer',
pre712: 'boolean',
},
searchSource: true,
defaults: {
@ -52,7 +50,6 @@ export function createSavedSearchClass(savedObjects: SavedObjectsStart) {
hits: 0,
sort: [],
version: 1,
pre712: false,
},
});
this.showInRecentlyAccessed = true;

View file

@ -23,7 +23,6 @@ export interface SavedSearch {
save: (saveOptions: SavedObjectSaveOpts) => Promise<string>;
lastSavedTitle?: string;
copyOnSave?: boolean;
pre712?: boolean;
hideChart?: boolean;
}
export interface SavedSearchLoader {

View file

@ -45,7 +45,6 @@ export const searchSavedObjectType: SavedObjectsType = {
title: { type: 'text' },
grid: { type: 'object', enabled: false },
version: { type: 'integer' },
pre712: { type: 'boolean' },
},
},
migrations: searchMigrations as any,

View file

@ -350,41 +350,4 @@ Object {
testMigrateMatchAllQuery(migrationFn);
});
});
describe('7.12.0', () => {
const migrationFn = searchMigrations['7.12.0'];
describe('migrateExistingSavedSearch', () => {
it('should add a new flag to existing saved searches', () => {
const migratedDoc = migrationFn(
{
type: 'search',
attributes: {
kibanaSavedObjectMeta: {},
},
},
savedObjectMigrationContext
);
const migratedPre712Flag = migratedDoc.attributes.pre712;
expect(migratedPre712Flag).toEqual(true);
});
it('should not modify a flag if it already exists', () => {
const migratedDoc = migrationFn(
{
type: 'search',
attributes: {
kibanaSavedObjectMeta: {},
pre712: false,
},
},
savedObjectMigrationContext
);
const migratedPre712Flag = migratedDoc.attributes.pre712;
expect(migratedPre712Flag).toEqual(false);
});
});
});
});

View file

@ -117,28 +117,9 @@ const migrateSearchSortToNestedArray: SavedObjectMigrationFn<any, any> = (doc) =
};
};
const migrateExistingSavedSearch: SavedObjectMigrationFn<any, any> = (doc) => {
if (!doc.attributes) {
return doc;
}
const pre712 = doc.attributes.pre712;
// pre712 already has a value
if (pre712 !== undefined) {
return doc;
}
return {
...doc,
attributes: {
...doc.attributes,
pre712: true,
},
};
};
export const searchMigrations = {
'6.7.2': flow(migrateMatchAllQuery),
'7.0.0': flow(setNewReferences),
'7.4.0': flow(migrateSearchSortToNestedArray),
'7.9.3': flow(migrateMatchAllQuery),
'7.12.0': flow(migrateExistingSavedSearch),
};

View file

@ -12,14 +12,11 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const testSubjects = getService('testSubjects');
const log = getService('log');
const retry = getService('retry');
const PageObjects = getPageObjects(['common', 'timePicker', 'discover']);
describe('index pattern with unmapped fields', () => {
const unmappedFieldsSwitchSelector = 'unmappedFieldsSwitch';
before(async () => {
await esArchiver.loadIfNeeded('unmapped_fields');
await kibanaServer.uiSettings.replace({
@ -37,7 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await esArchiver.unload('unmapped_fields');
});
it('unmapped fields do not exist on a new saved search', async () => {
it('unmapped fields exist on a new saved search', async () => {
const expectedHitCount = '4';
await retry.try(async function () {
expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount);
@ -46,13 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
// message is a mapped field
expect(allFields.includes('message')).to.be(true);
// sender is not a mapped field
expect(allFields.includes('sender')).to.be(false);
});
it('unmapped fields toggle does not exist on a new saved search', async () => {
await PageObjects.discover.openSidebarFieldFilter();
await testSubjects.existOrFail('filterSelectionPanel');
await testSubjects.missingOrFail('unmappedFieldsSwitch');
expect(allFields.includes('sender')).to.be(true);
});
it('unmapped fields exist on an existing saved search', async () => {
@ -66,21 +57,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(allFields.includes('sender')).to.be(true);
expect(allFields.includes('receiver')).to.be(true);
});
it('unmapped fields toggle exists on an existing saved search', async () => {
await PageObjects.discover.openSidebarFieldFilter();
await testSubjects.existOrFail('filterSelectionPanel');
await testSubjects.existOrFail(unmappedFieldsSwitchSelector);
expect(await testSubjects.isEuiSwitchChecked(unmappedFieldsSwitchSelector)).to.be(true);
});
it('switching unmapped fields toggle off hides unmapped fields', async () => {
await testSubjects.setEuiSwitch(unmappedFieldsSwitchSelector, 'uncheck');
await PageObjects.discover.closeSidebarFieldFilter();
const allFields = await PageObjects.discover.getAllFieldNames();
expect(allFields.includes('message')).to.be(true);
expect(allFields.includes('sender')).to.be(false);
expect(allFields.includes('receiver')).to.be(false);
});
});
}