allow filtering index pattern UI for runtime fields (#124114)

* allow filtering index pattern UI for runtime fields

* fix namespace error

* add multi select filters

* add fix for failing tests

* test fixes
This commit is contained in:
Shivindera Singh 2022-02-09 10:13:59 +01:00 committed by GitHub
parent ecff412e22
commit 01d479108b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 430 additions and 82 deletions

View file

@ -141,6 +141,24 @@ exports[`IndexedFieldsTable IndexedFieldsTable with rollup index pattern should
"name": "amount",
"type": "long",
},
Object {
"displayName": "runtime",
"excluded": false,
"format": "",
"hasRuntime": true,
"info": Array [],
"isMapped": false,
"isUserEditable": false,
"kbnType": "number",
"name": "runtime",
"runtimeField": Object {
"script": Object {
"source": "emit('Hello');",
},
"type": "long",
},
"type": "long",
},
]
}
/>
@ -182,6 +200,43 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = `
</div>
`;
exports[`IndexedFieldsTable should filter based on the schema filter 1`] = `
<div>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getFormatterForFieldNoDefault": [Function],
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"displayName": "runtime",
"excluded": false,
"format": "",
"hasRuntime": true,
"info": Array [],
"isMapped": false,
"isUserEditable": false,
"kbnType": "number",
"name": "runtime",
"runtimeField": Object {
"script": Object {
"source": "emit('Hello');",
},
"type": "long",
},
"type": "long",
},
]
}
/>
</div>
`;
exports[`IndexedFieldsTable should filter based on the type filter 1`] = `
<div>
<Table
@ -291,6 +346,24 @@ exports[`IndexedFieldsTable should render normally 1`] = `
"name": "amount",
"type": "long",
},
Object {
"displayName": "runtime",
"excluded": false,
"format": "",
"hasRuntime": true,
"info": Array [],
"isMapped": false,
"isUserEditable": false,
"kbnType": "number",
"name": "runtime",
"runtimeField": Object {
"script": Object {
"source": "emit('Hello');",
},
"type": "long",
},
"type": "long",
},
]
}
/>

View file

@ -11,6 +11,7 @@ import { shallow, ShallowWrapper } from 'enzyme';
import { DataViewField, DataView, DataViewType } from 'src/plugins/data_views/public';
import { IndexedFieldsTable } from './indexed_fields_table';
import { getFieldInfo } from '../../utils';
import { RuntimeField } from 'src/plugins/data_views/common';
jest.mock('@elastic/eui', () => ({
EuiFlexGroup: 'eui-flex-group',
@ -67,11 +68,12 @@ const rollupIndexPattern = {
} as unknown as DataView;
const mockFieldToIndexPatternField = (
spec: Record<string, string | string[] | boolean | undefined>
spec: Record<string, string | string[] | boolean | undefined | RuntimeField>
) => {
return new DataViewField(spec as unknown as DataViewField['spec']);
};
const runtimeField: RuntimeField = { type: 'long', script: { source: "emit('Hello');" } };
const fields = [
{
name: 'Elastic',
@ -88,6 +90,11 @@ const fields = [
isUserEditable: true,
},
{ name: 'amount', displayName: 'amount', esTypes: ['long'], isUserEditable: true },
{
name: 'runtime',
displayName: 'runtime',
runtimeField,
},
].map(mockFieldToIndexPatternField);
describe('IndexedFieldsTable', () => {
@ -100,7 +107,8 @@ describe('IndexedFieldsTable', () => {
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter=""
indexedFieldTypeFilter={[]}
schemaFieldTypeFilter={[]}
fieldFilter=""
/>
).dive();
@ -120,7 +128,8 @@ describe('IndexedFieldsTable', () => {
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter=""
indexedFieldTypeFilter={[]}
schemaFieldTypeFilter={[]}
fieldFilter=""
/>
).dive();
@ -141,13 +150,36 @@ describe('IndexedFieldsTable', () => {
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter=""
indexedFieldTypeFilter={[]}
schemaFieldTypeFilter={[]}
fieldFilter=""
/>
).dive();
await new Promise((resolve) => process.nextTick(resolve));
component.setProps({ indexedFieldTypeFilter: 'date' });
component.setProps({ indexedFieldTypeFilter: ['date'] });
component.update();
expect(component).toMatchSnapshot();
});
test('should filter based on the schema filter', async () => {
const component: ShallowWrapper<any, Readonly<{}>, React.Component<{}, {}, any>> = shallow(
<IndexedFieldsTable
fields={fields}
indexPattern={indexPattern}
helpers={helpers}
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter={[]}
schemaFieldTypeFilter={[]}
fieldFilter=""
/>
).dive();
await new Promise((resolve) => process.nextTick(resolve));
component.setProps({ schemaFieldTypeFilter: ['runtime'] });
component.update();
expect(component).toMatchSnapshot();
@ -163,7 +195,8 @@ describe('IndexedFieldsTable', () => {
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter=""
indexedFieldTypeFilter={[]}
schemaFieldTypeFilter={[]}
fieldFilter=""
/>
).dive();

View file

@ -19,7 +19,8 @@ interface IndexedFieldsTableProps {
fields: DataViewField[];
indexPattern: DataView;
fieldFilter?: string;
indexedFieldTypeFilter?: string;
indexedFieldTypeFilter: string[];
schemaFieldTypeFilter: string[];
helpers: {
editField: (fieldName: string) => void;
deleteField: (fieldName: string) => void;
@ -93,7 +94,8 @@ class IndexedFields extends Component<IndexedFieldsTableProps, IndexedFieldsTabl
(state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.fieldFilter,
(state: IndexedFieldsTableState, props: IndexedFieldsTableProps) =>
props.indexedFieldTypeFilter,
(fields, fieldFilter, indexedFieldTypeFilter) => {
(state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.schemaFieldTypeFilter,
(fields, fieldFilter, indexedFieldTypeFilter, schemaFieldTypeFilter) => {
if (fieldFilter) {
const normalizedFieldFilter = fieldFilter.toLowerCase();
fields = fields.filter(
@ -103,14 +105,34 @@ class IndexedFields extends Component<IndexedFieldsTableProps, IndexedFieldsTabl
);
}
if (indexedFieldTypeFilter) {
if (indexedFieldTypeFilter.length) {
// match conflict fields
fields = fields.filter((field) => {
if (indexedFieldTypeFilter === 'conflict' && field.kbnType === 'conflict') {
if (indexedFieldTypeFilter.includes('conflict') && field.kbnType === 'conflict') {
return true;
}
if (
'runtimeField' in field &&
field.runtimeField?.type &&
indexedFieldTypeFilter.includes(field.runtimeField?.type)
) {
return true;
}
// match one of multiple types on a field
return field.esTypes?.length && field.esTypes?.indexOf(indexedFieldTypeFilter) !== -1;
return (
field.esTypes?.length &&
field.esTypes.filter((val) => indexedFieldTypeFilter.includes(val)).length
);
});
}
if (schemaFieldTypeFilter.length) {
// match fields of schema type
fields = fields.filter((field) => {
return (
(schemaFieldTypeFilter.includes('runtime') && 'runtimeField' in field) ||
(schemaFieldTypeFilter.includes('indexed') && !('runtimeField' in field))
);
});
}

View file

@ -68,6 +68,7 @@ describe('ScriptedFieldsTable', () => {
helpers={helpers}
painlessDocLink={'painlessDoc'}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();
@ -86,6 +87,7 @@ describe('ScriptedFieldsTable', () => {
helpers={helpers}
painlessDocLink={'painlessDoc'}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();
@ -117,6 +119,7 @@ describe('ScriptedFieldsTable', () => {
painlessDocLink={'painlessDoc'}
helpers={helpers}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();
@ -125,7 +128,7 @@ describe('ScriptedFieldsTable', () => {
await component.update(); // Fire `componentWillMount()`
await component.update(); // Force update the component post async actions
component.setProps({ scriptedFieldLanguageFilter: 'painless' });
component.setProps({ scriptedFieldLanguageFilter: ['painless'] });
component.update();
expect(component).toMatchSnapshot();
@ -142,6 +145,7 @@ describe('ScriptedFieldsTable', () => {
painlessDocLink={'painlessDoc'}
helpers={helpers}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();
@ -162,6 +166,7 @@ describe('ScriptedFieldsTable', () => {
helpers={helpers}
painlessDocLink={'painlessDoc'}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();
@ -189,6 +194,7 @@ describe('ScriptedFieldsTable', () => {
helpers={helpers}
painlessDocLink={'painlessDoc'}
saveIndexPattern={async () => {}}
scriptedFieldLanguageFilter={[]}
/>
).dive();

View file

@ -23,7 +23,7 @@ import { useKibana } from '../../../../../../plugins/kibana_react/public';
interface ScriptedFieldsTableProps {
indexPattern: DataView;
fieldFilter?: string;
scriptedFieldLanguageFilter?: string;
scriptedFieldLanguageFilter: string[];
helpers: {
redirectToRoute: Function;
getRouteHref?: Function;
@ -92,9 +92,9 @@ class ScriptedFields extends Component<ScriptedFieldsTableProps, ScriptedFieldsT
let languageFilteredFields = fields;
if (scriptedFieldLanguageFilter) {
languageFilteredFields = fields.filter(
(field) => field.lang === this.props.scriptedFieldLanguageFilter
if (scriptedFieldLanguageFilter.length) {
languageFilteredFields = fields.filter((field) =>
scriptedFieldLanguageFilter.includes(field.lang)
);
}

View file

@ -9,15 +9,18 @@
import React, { useState, useCallback, useEffect, Fragment, useMemo, useRef } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import {
EuiFilterButton,
EuiFilterGroup,
EuiFlexGroup,
EuiFlexItem,
EuiPopover,
EuiTabbedContent,
EuiTabbedContentTab,
EuiSpacer,
EuiFieldSearch,
EuiSelect,
EuiSelectOption,
EuiButton,
EuiFilterSelectItem,
FilterChecked,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { fieldWildcardMatcher } from '../../../../../kibana_utils/public';
@ -34,7 +37,7 @@ import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from '../
import { SourceFiltersTable } from '../source_filters_table';
import { IndexedFieldsTable } from '../indexed_fields_table';
import { ScriptedFieldsTable } from '../scripted_fields_table';
import { getTabs, getPath, convertToEuiSelectOption } from './utils';
import { getTabs, getPath, convertToEuiFilterOptions } from './utils';
import { getFieldInfo } from '../../utils';
interface TabsProps extends Pick<RouteComponentProps, 'history' | 'location'> {
@ -44,6 +47,12 @@ interface TabsProps extends Pick<RouteComponentProps, 'history' | 'location'> {
refreshFields: () => void;
}
interface FilterItems {
value: string;
name: string;
checked?: FilterChecked;
}
const searchAriaLabel = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.searchAria',
{
@ -51,6 +60,10 @@ const searchAriaLabel = i18n.translate(
}
);
const filterLabel = i18n.translate('indexPatternManagement.editIndexPattern.fields.filter', {
defaultMessage: 'Field type',
});
const filterAriaLabel = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.filterAria',
{
@ -58,6 +71,45 @@ const filterAriaLabel = i18n.translate(
}
);
const schemaFilterLabel = i18n.translate('indexPatternManagement.editIndexPattern.fields.schema', {
defaultMessage: 'Schema type',
});
const schemaAriaLabel = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.schemaAria',
{
defaultMessage: 'Filter schema types',
}
);
const scriptedFieldFilterLabel = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.scriptedFieldFilter',
{
defaultMessage: 'All languages',
}
);
const scriptedFieldAriaLabel = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.scriptedFieldFilterAria',
{
defaultMessage: 'Filter scripted field languages',
}
);
const schemaOptionRuntime = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.runtime',
{
defaultMessage: 'Runtime',
}
);
const schemaOptionIndexed = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.indexed',
{
defaultMessage: 'Indexed',
}
);
const filterPlaceholder = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.filterPlaceholder',
{
@ -83,16 +135,53 @@ export function Tabs({
const { application, uiSettings, docLinks, dataViewFieldEditor, overlays, theme } =
useKibana<IndexPatternManagmentContext>().services;
const [fieldFilter, setFieldFilter] = useState<string>('');
const [indexedFieldTypeFilter, setIndexedFieldTypeFilter] = useState<string>('');
const [scriptedFieldLanguageFilter, setScriptedFieldLanguageFilter] = useState<string>('');
const [indexedFieldTypes, setIndexedFieldType] = useState<EuiSelectOption[]>([]);
const [scriptedFieldLanguages, setScriptedFieldLanguages] = useState<EuiSelectOption[]>([]);
const [syncingStateFunc, setSyncingStateFunc] = useState<any>({
getCurrentTab: () => TAB_INDEXED_FIELDS,
});
const [scriptedFieldLanguageFilter, setScriptedFieldLanguageFilter] = useState<string[]>([]);
const [isScriptedFieldFilterOpen, setIsScriptedFieldFilterOpen] = useState(false);
const [scriptedFieldLanguages, setScriptedFieldLanguages] = useState<FilterItems[]>([]);
const [indexedFieldTypeFilter, setIndexedFieldTypeFilter] = useState<string[]>([]);
const [isIndexedFilterOpen, setIsIndexedFilterOpen] = useState(false);
const [indexedFieldTypes, setIndexedFieldTypes] = useState<FilterItems[]>([]);
const [schemaFieldTypeFilter, setSchemaFieldTypeFilter] = useState<string[]>([]);
const [isSchemaFilterOpen, setIsSchemaFilterOpen] = useState(false);
const [schemaItems, setSchemaItems] = useState<FilterItems[]>([
{
value: 'runtime',
name: schemaOptionRuntime,
},
{
value: 'indexed',
name: schemaOptionIndexed,
},
]);
const closeEditorHandler = useRef<() => void | undefined>();
const { DeleteRuntimeFieldProvider } = dataViewFieldEditor;
const updateFilterItem = (
items: FilterItems[],
index: number,
updater: (a: FilterItems[]) => void
) => {
if (!items[index]) {
return;
}
const newItems = [...items];
switch (newItems[index].checked) {
case 'on':
newItems[index].checked = undefined;
break;
default:
newItems[index].checked = 'on';
}
updater(newItems);
};
const refreshFilters = useCallback(() => {
const tempIndexedFieldTypes: string[] = [];
const tempScriptedFieldLanguages: string[] = [];
@ -113,10 +202,8 @@ export function Tabs({
}
});
setIndexedFieldType(convertToEuiSelectOption(tempIndexedFieldTypes, 'indexedFiledTypes'));
setScriptedFieldLanguages(
convertToEuiSelectOption(tempScriptedFieldLanguages, 'scriptedFieldLanguages')
);
setIndexedFieldTypes(convertToEuiFilterOptions(tempIndexedFieldTypes));
setScriptedFieldLanguages(convertToEuiFilterOptions(tempScriptedFieldLanguages));
}, [indexPattern]);
const closeFieldEditor = useCallback(() => {
@ -172,13 +259,92 @@ export function Tabs({
{type === TAB_INDEXED_FIELDS && indexedFieldTypes.length > 0 && (
<>
<EuiFlexItem grow={false}>
<EuiSelect
options={indexedFieldTypes}
value={indexedFieldTypeFilter}
onChange={(e) => setIndexedFieldTypeFilter(e.target.value)}
data-test-subj="indexedFieldTypeFilterDropdown"
aria-label={filterAriaLabel}
/>
<EuiFilterGroup>
<EuiPopover
anchorPosition="downCenter"
data-test-subj="indexedFieldTypeFilterDropdown-popover"
button={
<EuiFilterButton
aria-label={filterAriaLabel}
data-test-subj="indexedFieldTypeFilterDropdown"
iconType="arrowDown"
onClick={() => setIsIndexedFilterOpen(!isIndexedFilterOpen)}
isSelected={isIndexedFilterOpen}
numFilters={indexedFieldTypes.length}
hasActiveFilters={!!indexedFieldTypes.find((item) => item.checked === 'on')}
numActiveFilters={
indexedFieldTypes.filter((item) => item.checked === 'on').length
}
>
{filterLabel}
</EuiFilterButton>
}
isOpen={isIndexedFilterOpen}
closePopover={() => setIsIndexedFilterOpen(false)}
>
{indexedFieldTypes.map((item, index) => (
<EuiFilterSelectItem
checked={item.checked}
key={item.value}
onClick={() => {
setIndexedFieldTypeFilter(
item.checked
? indexedFieldTypeFilter.filter((f) => f !== item.value)
: [...indexedFieldTypeFilter, item.value]
);
updateFilterItem(indexedFieldTypes, index, setIndexedFieldTypes);
}}
data-test-subj={`indexedFieldTypeFilterDropdown-option-${item.value}${
item.checked ? '-checked' : ''
}`}
>
{item.name}
</EuiFilterSelectItem>
))}
</EuiPopover>
<EuiPopover
anchorPosition="downCenter"
data-test-subj="schemaFieldTypeFilterDropdown-popover"
button={
<EuiFilterButton
aria-label={schemaAriaLabel}
data-test-subj="schemaFieldTypeFilterDropdown"
iconType="arrowDown"
onClick={() => setIsSchemaFilterOpen(!isSchemaFilterOpen)}
isSelected={isSchemaFilterOpen}
numFilters={schemaItems.length}
hasActiveFilters={!!schemaItems.find((item) => item.checked === 'on')}
numActiveFilters={
schemaItems.filter((item) => item.checked === 'on').length
}
>
{schemaFilterLabel}
</EuiFilterButton>
}
isOpen={isSchemaFilterOpen}
closePopover={() => setIsSchemaFilterOpen(false)}
>
{schemaItems.map((item, index) => (
<EuiFilterSelectItem
checked={item.checked}
key={item.value}
onClick={() => {
setSchemaFieldTypeFilter(
item.checked
? schemaFieldTypeFilter.filter((f) => f !== item.value)
: [...schemaFieldTypeFilter, item.value]
);
updateFilterItem(schemaItems, index, setSchemaItems);
}}
data-test-subj={`schemaFieldTypeFilterDropdown-option-${item.value}${
item.checked ? '-checked' : ''
}`}
>
{item.name}
</EuiFilterSelectItem>
))}
</EuiPopover>
</EuiFilterGroup>
</EuiFlexItem>
{userEditPermission && (
<EuiFlexItem grow={false}>
@ -191,12 +357,52 @@ export function Tabs({
)}
{type === TAB_SCRIPTED_FIELDS && scriptedFieldLanguages.length > 0 && (
<EuiFlexItem grow={false}>
<EuiSelect
options={scriptedFieldLanguages}
value={scriptedFieldLanguageFilter}
onChange={(e) => setScriptedFieldLanguageFilter(e.target.value)}
data-test-subj="scriptedFieldLanguageFilterDropdown"
/>
<EuiFilterGroup>
<EuiPopover
anchorPosition="downCenter"
data-test-subj="scriptedFieldLanguageFilterDropdown-popover"
button={
<EuiFilterButton
aria-label={scriptedFieldAriaLabel}
data-test-subj="scriptedFieldLanguageFilterDropdown"
iconType="arrowDown"
onClick={() => setIsScriptedFieldFilterOpen(!isScriptedFieldFilterOpen)}
isSelected={isScriptedFieldFilterOpen}
numFilters={scriptedFieldLanguages.length}
hasActiveFilters={
!!scriptedFieldLanguages.find((item) => item.checked === 'on')
}
numActiveFilters={
scriptedFieldLanguages.filter((item) => item.checked === 'on').length
}
>
{scriptedFieldFilterLabel}
</EuiFilterButton>
}
isOpen={isScriptedFieldFilterOpen}
closePopover={() => setIsScriptedFieldFilterOpen(false)}
>
{scriptedFieldLanguages.map((item, index) => (
<EuiFilterSelectItem
checked={item.checked}
key={item.value}
onClick={() => {
setScriptedFieldLanguageFilter(
item.checked
? scriptedFieldLanguageFilter.filter((f) => f !== item.value)
: [...scriptedFieldLanguageFilter, item.value]
);
updateFilterItem(scriptedFieldLanguages, index, setScriptedFieldLanguages);
}}
data-test-subj={`scriptedFieldLanguageFilterDropdown-option-${item.value}${
item.checked ? '-checked' : ''
}`}
>
{item.name}
</EuiFilterSelectItem>
))}
</EuiPopover>
</EuiFilterGroup>
</EuiFlexItem>
)}
</EuiFlexGroup>
@ -206,8 +412,13 @@ export function Tabs({
fieldFilter,
indexedFieldTypeFilter,
indexedFieldTypes,
isIndexedFilterOpen,
scriptedFieldLanguageFilter,
scriptedFieldLanguages,
isScriptedFieldFilterOpen,
schemaItems,
schemaFieldTypeFilter,
isSchemaFilterOpen,
openFieldEditor,
userEditPermission,
]
@ -230,6 +441,7 @@ export function Tabs({
fieldFilter={fieldFilter}
fieldWildcardMatcher={fieldWildcardMatcherDecorated}
indexedFieldTypeFilter={indexedFieldTypeFilter}
schemaFieldTypeFilter={schemaFieldTypeFilter}
helpers={{
editField: openFieldEditor,
deleteField,
@ -289,6 +501,7 @@ export function Tabs({
history,
indexPattern,
indexedFieldTypeFilter,
schemaFieldTypeFilter,
refreshFilters,
scriptedFieldLanguageFilter,
saveIndexPattern,

View file

@ -105,36 +105,11 @@ export function getPath(field: DataViewField, indexPattern: DataView) {
return `/dataView/${indexPattern?.id}/field/${encodeURIComponent(field.name)}`;
}
const allTypesDropDown = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.allTypesDropDown',
{
defaultMessage: 'All field types',
}
);
const allLangsDropDown = i18n.translate(
'indexPatternManagement.editIndexPattern.fields.allLangsDropDown',
{
defaultMessage: 'All languages',
}
);
export function convertToEuiSelectOption(options: string[], type: string) {
const euiOptions =
options.length > 0
? [
{
value: '',
text: type === 'scriptedFieldLanguages' ? allLangsDropDown : allTypesDropDown,
},
]
: [];
return euiOptions.concat(
uniq(options).map((option) => {
return {
value: option,
text: option,
};
})
);
export function convertToEuiFilterOptions(options: string[]) {
return uniq(options).map((option) => {
return {
value: option,
name: option,
};
});
}

View file

@ -44,6 +44,7 @@ export default function ({ getService, getPageObjects }) {
expect(fieldType).to.be('keyword');
}
});
await PageObjects.settings.clearFieldTypeFilter('keyword');
await PageObjects.settings.setFieldTypeFilter('long');
@ -54,6 +55,7 @@ export default function ({ getService, getPageObjects }) {
expect(fieldType).to.be('long');
}
});
await PageObjects.settings.clearFieldTypeFilter('long');
});
});
}

View file

@ -66,6 +66,7 @@ export default function ({ getService, getPageObjects }) {
expect(lang).to.be('painless');
}
});
await PageObjects.settings.clearScriptedFieldLanguageFilter('painless');
await PageObjects.settings.setScriptedFieldLanguageFilter('expression');
@ -76,6 +77,7 @@ export default function ({ getService, getPageObjects }) {
expect(lang).to.be('expression');
}
});
await PageObjects.settings.clearScriptedFieldLanguageFilter('expression');
});
});
}

View file

@ -258,18 +258,44 @@ export class SettingsPageObject extends FtrService {
);
}
async clearFieldTypeFilter(type: string) {
await this.testSubjects.clickWhenNotDisabled('indexedFieldTypeFilterDropdown');
await this.testSubjects.existOrFail('indexedFieldTypeFilterDropdown-popover');
await this.testSubjects.existOrFail(`indexedFieldTypeFilterDropdown-option-${type}-checked`);
await this.testSubjects.click(`indexedFieldTypeFilterDropdown-option-${type}-checked`);
await this.testSubjects.existOrFail(`indexedFieldTypeFilterDropdown-option-${type}`);
await this.browser.pressKeys(this.browser.keys.ESCAPE);
}
async setFieldTypeFilter(type: string) {
await this.find.clickByCssSelector(
'select[data-test-subj="indexedFieldTypeFilterDropdown"] > option[value="' + type + '"]'
await this.testSubjects.clickWhenNotDisabled('indexedFieldTypeFilterDropdown');
await this.testSubjects.existOrFail('indexedFieldTypeFilterDropdown-popover');
await this.testSubjects.existOrFail(`indexedFieldTypeFilterDropdown-option-${type}`);
await this.testSubjects.click(`indexedFieldTypeFilterDropdown-option-${type}`);
await this.testSubjects.existOrFail(`indexedFieldTypeFilterDropdown-option-${type}-checked`);
await this.browser.pressKeys(this.browser.keys.ESCAPE);
}
async clearScriptedFieldLanguageFilter(type: string) {
await this.testSubjects.clickWhenNotDisabled('scriptedFieldLanguageFilterDropdown');
await this.testSubjects.existOrFail('scriptedFieldLanguageFilterDropdown-popover');
await this.testSubjects.existOrFail(
`scriptedFieldLanguageFilterDropdown-option-${type}-checked`
);
await this.testSubjects.click(`scriptedFieldLanguageFilterDropdown-option-${type}-checked`);
await this.testSubjects.existOrFail(`scriptedFieldLanguageFilterDropdown-option-${type}`);
await this.browser.pressKeys(this.browser.keys.ESCAPE);
}
async setScriptedFieldLanguageFilter(language: string) {
await this.find.clickByCssSelector(
'select[data-test-subj="scriptedFieldLanguageFilterDropdown"] > option[value="' +
language +
'"]'
await this.testSubjects.clickWhenNotDisabled('scriptedFieldLanguageFilterDropdown');
await this.testSubjects.existOrFail('scriptedFieldLanguageFilterDropdown-popover');
await this.testSubjects.existOrFail(`scriptedFieldLanguageFilterDropdown-option-${language}`);
await this.testSubjects.click(`scriptedFieldLanguageFilterDropdown-option-${language}`);
await this.testSubjects.existOrFail(
`scriptedFieldLanguageFilterDropdown-option-${language}-checked`
);
await this.browser.pressKeys(this.browser.keys.ESCAPE);
}
async filterField(name: string) {

View file

@ -4143,8 +4143,6 @@
"indexPatternManagement.editIndexPattern.deleteButton": "削除",
"indexPatternManagement.editIndexPattern.deprecation": "スクリプトフィールドは廃止予定です。代わりに{runtimeDocs}を使用してください。",
"indexPatternManagement.editIndexPattern.fields.addFieldButtonLabel": "フィールドの追加",
"indexPatternManagement.editIndexPattern.fields.allLangsDropDown": "すべての言語",
"indexPatternManagement.editIndexPattern.fields.allTypesDropDown": "すべてのフィールドタイプ",
"indexPatternManagement.editIndexPattern.fields.conflictModal.closeBtn": "閉じる",
"indexPatternManagement.editIndexPattern.fields.conflictModal.description": "{fieldName}フィールドの型がインデックス全体で変更され、検索、視覚化、他の分析で使用できない可能性があります。",
"indexPatternManagement.editIndexPattern.fields.conflictModal.title": "このフィールドは型が競合しています",

View file

@ -3933,8 +3933,6 @@
"indexPatternManagement.editIndexPattern.deleteButton": "删除",
"indexPatternManagement.editIndexPattern.deprecation": "脚本字段已弃用。改用 {runtimeDocs}。",
"indexPatternManagement.editIndexPattern.fields.addFieldButtonLabel": "添加字段",
"indexPatternManagement.editIndexPattern.fields.allLangsDropDown": "所有语言",
"indexPatternManagement.editIndexPattern.fields.allTypesDropDown": "所有字段类型",
"indexPatternManagement.editIndexPattern.fields.conflictModal.closeBtn": "关闭",
"indexPatternManagement.editIndexPattern.fields.conflictModal.description": "{fieldName} 字段的类型在不同索引中会有所不同,并且可能无法用于搜索、可视化和其他分析。",
"indexPatternManagement.editIndexPattern.fields.conflictModal.title": "此字段存在类型冲突",