Skip to content

Commit

Permalink
[8.x] [Data View Mgmt] Implement state service (#193660) (#194022)
Browse files Browse the repository at this point in the history
# Backport

This will backport the following commits from `main` to `8.x`:
- [[Data View Mgmt] Implement state service
(#193660)](#193660)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Matthew
Kime","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-09-25T14:37:17Z","message":"[Data
View Mgmt] Implement state service (#193660)\n\n##
Summary\r\n\r\nIntermediate step in converting Data View Management to
DataViewLazy.\r\nMoved `useCallback` functionality into central service
so much of the\r\nstate functionality is in one place and easier to
understand and\r\nrefactor.\r\n\r\nPart of
https://github.com/elastic/kibana/issues/178926\r\n\r\nBroken out from
#190292 which\r\ntried to do
everything in one go and became too
messy.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Julia Rechkunova
<[email protected]>","sha":"d772a11c74af1efd05242516900f06cbeb00dd6f","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Data
Views","Feature:Kibana
Management","release_note:skip","v9.0.0","Team:DataDiscovery","backport:prev-major"],"title":"[Data
View Mgmt] Implement state
service","number":193660,"url":"https://github.com/elastic/kibana/pull/193660","mergeCommit":{"message":"[Data
View Mgmt] Implement state service (#193660)\n\n##
Summary\r\n\r\nIntermediate step in converting Data View Management to
DataViewLazy.\r\nMoved `useCallback` functionality into central service
so much of the\r\nstate functionality is in one place and easier to
understand and\r\nrefactor.\r\n\r\nPart of
https://github.com/elastic/kibana/issues/178926\r\n\r\nBroken out from
#190292 which\r\ntried to do
everything in one go and became too
messy.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Julia Rechkunova
<[email protected]>","sha":"d772a11c74af1efd05242516900f06cbeb00dd6f"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193660","number":193660,"mergeCommit":{"message":"[Data
View Mgmt] Implement state service (#193660)\n\n##
Summary\r\n\r\nIntermediate step in converting Data View Management to
DataViewLazy.\r\nMoved `useCallback` functionality into central service
so much of the\r\nstate functionality is in one place and easier to
understand and\r\nrefactor.\r\n\r\nPart of
https://github.com/elastic/kibana/issues/178926\r\n\r\nBroken out from
#190292 which\r\ntried to do
everything in one go and became too
messy.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Julia Rechkunova
<[email protected]>","sha":"d772a11c74af1efd05242516900f06cbeb00dd6f"}}]}]
BACKPORT-->

Co-authored-by: Matthew Kime <[email protected]>
  • Loading branch information
kibanamachine and mattkime authored Sep 30, 2024
1 parent 7eb3bdd commit 0308537
Show file tree
Hide file tree
Showing 13 changed files with 551 additions and 252 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,23 @@ import { IndexPatternManagmentContext } from '../../types';
import { getEditBreadcrumbs } from '../breadcrumbs';

const EditIndexPatternCont: React.FC<RouteComponentProps<{ id: string }>> = ({ ...props }) => {
const { dataViews, setBreadcrumbs, notifications } =
const { dataViews, setBreadcrumbs, notifications, dataViewMgmtService } =
useKibana<IndexPatternManagmentContext>().services;
const [error, setError] = useState<Error | undefined>();
const [indexPattern, setIndexPattern] = useState<DataView>();

useEffect(() => {
dataViews
.get(decodeURIComponent(props.match.params.id))
.get(decodeURIComponent(props.match.params.id), undefined, true)
.then((ip: DataView) => {
dataViewMgmtService.setDataView(ip);
setIndexPattern(ip);
setBreadcrumbs(getEditBreadcrumbs(ip));
})
.catch((err) => {
setError(err);
});
}, [dataViews, props.match.params.id, setBreadcrumbs, setError]);
}, [dataViews, props.match.params.id, setBreadcrumbs, setError, dataViewMgmtService]);

if (error) {
const [errorTitle, errorMessage] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
META_FIELDS,
RuntimeField,
} from '@kbn/data-views-plugin/public';
import { AbstractDataView } from '@kbn/data-views-plugin/common';
import {
SavedObjectRelation,
SavedObjectManagementTypeInfo,
Expand All @@ -53,6 +54,13 @@ import { ScriptedFieldsTable } from '../scripted_fields_table';
import { RelationshipsTable } from '../relationships_table';
import { getTabs, getPath, convertToEuiFilterOptions } from './utils';
import { getFieldInfo } from '../../utils';
import { useStateSelector } from '../../../management_app/state_utils';

import {
fieldsSelector,
indexedFieldTypeSelector,
scriptedFieldLangsSelector,
} from '../../../management_app/data_view_mgmt_selectors';

interface TabsProps extends Pick<RouteComponentProps, 'history' | 'location'> {
indexPattern: DataView;
Expand Down Expand Up @@ -165,7 +173,6 @@ const SCHEMA_ITEMS: FilterItems[] = [
export const Tabs: React.FC<TabsProps> = ({
indexPattern,
saveIndexPattern,
fields,
history,
refreshFields,
relationships,
Expand All @@ -183,6 +190,7 @@ export const Tabs: React.FC<TabsProps> = ({
http,
application,
savedObjectsManagement,
dataViewMgmtService,
...startServices
} = useKibana<IndexPatternManagmentContext>().services;
const [fieldFilter, setFieldFilter] = useState<string>('');
Expand All @@ -200,20 +208,24 @@ export const Tabs: React.FC<TabsProps> = ({
}>({});
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 fields = useStateSelector(dataViewMgmtService.state$, fieldsSelector);
const indexedFieldTypes = convertToEuiFilterOptions(
useStateSelector(dataViewMgmtService.state$, indexedFieldTypeSelector)
);
const scriptedFieldLanguages = useStateSelector(
dataViewMgmtService.state$,
scriptedFieldLangsSelector
);
const closeEditorHandler = useRef<() => void | undefined>();
const { DeleteRuntimeFieldProvider } = dataViewFieldEditor;

const filteredIndexedFieldTypeFilter = useMemo(() => {
return uniq(
indexedFieldTypeFilter.filter((fieldType) =>
indexedFieldTypes.some((item) => item.value === fieldType)
)
return indexedFieldTypeFilter.filter((fieldType) =>
indexedFieldTypes.some((item) => item.value === fieldType)
);
}, [indexedFieldTypeFilter, indexedFieldTypes]);

Expand Down Expand Up @@ -253,55 +265,6 @@ export const Tabs: React.FC<TabsProps> = ({
[syncingStateFunc]
);

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[] = [];
indexPattern.fields.getAll().forEach((field) => {
if (field.scripted) {
if (field.lang) {
tempScriptedFieldLanguages.push(field.lang);
}
} else {
// for conflicted fields, add conflict as a type
if (field.type === 'conflict') {
tempIndexedFieldTypes.push('conflict');
}
if (field.esTypes) {
// add all types, may be multiple
field.esTypes.forEach((item) => tempIndexedFieldTypes.push(item));
}
}
});

setIndexedFieldTypes(convertToEuiFilterOptions(tempIndexedFieldTypes));
setScriptedFieldLanguages(convertToEuiFilterOptions(tempScriptedFieldLanguages));
// need to reset based on changes to fields but indexPattern is the same
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [indexPattern, fields]);

const closeFieldEditor = useCallback(() => {
if (closeEditorHandler.current) {
closeEditorHandler.current();
Expand All @@ -321,10 +284,6 @@ export const Tabs: React.FC<TabsProps> = ({
[dataViewFieldEditor, indexPattern, refreshFields]
);

useEffect(() => {
refreshFilters();
}, [indexPattern, indexPattern.fields, refreshFilters]);

useEffect(() => {
return () => {
// When the component unmounts, make sure to close the field editor
Expand All @@ -340,6 +299,7 @@ export const Tabs: React.FC<TabsProps> = ({
const refreshRef = useRef<HTMLButtonElement>(null);

const userEditPermission = dataViews.getCanSaveSync();

const getFilterSection = useCallback(
(type: string) => {
return (
Expand Down Expand Up @@ -517,12 +477,14 @@ export const Tabs: React.FC<TabsProps> = ({
checked={item.checked}
key={item.value}
onClick={() => {
// this does the filtering
setScriptedFieldLanguageFilter(
item.checked
? scriptedFieldLanguageFilter.filter((f) => f !== item.value)
: [...scriptedFieldLanguageFilter, item.value]
);
updateFilterItem(scriptedFieldLanguages, index, setScriptedFieldLanguages);
// updates the UI
dataViewMgmtService.setScriptedFieldLangSelection(index);
}}
data-test-subj={`scriptedFieldLanguageFilterDropdown-option-${item.value}${
item.checked ? '-checked' : ''
Expand All @@ -539,6 +501,7 @@ export const Tabs: React.FC<TabsProps> = ({
);
},
[
dataViewMgmtService,
fieldFilter,
filteredSchemaFieldTypeFilter,
filteredIndexedFieldTypeFilter,
Expand Down Expand Up @@ -606,7 +569,7 @@ export const Tabs: React.FC<TabsProps> = ({
history.push(getPath(field, indexPattern));
},
}}
onRemoveField={refreshFilters}
onRemoveField={() => dataViewMgmtService.refreshFields()}
painlessDocLink={docLinks.links.scriptedFields.painless}
userEditPermission={dataViews.getCanSaveSync()}
/>
Expand All @@ -619,11 +582,13 @@ export const Tabs: React.FC<TabsProps> = ({
{getFilterSection(type)}
<EuiSpacer size="m" />
<SourceFiltersTable
saveIndexPattern={saveIndexPattern}
saveIndexPattern={async (dv: AbstractDataView) => {
await saveIndexPattern(dv);
dataViewMgmtService.refreshFields();
}}
indexPattern={indexPattern}
filterFilter={fieldFilter}
fieldWildcardMatcher={fieldWildcardMatcherDecorated}
onAddOrRemoveFilter={refreshFilters}
/>
</Fragment>
);
Expand Down Expand Up @@ -655,7 +620,6 @@ export const Tabs: React.FC<TabsProps> = ({
indexPattern,
filteredIndexedFieldTypeFilter,
filteredSchemaFieldTypeFilter,
refreshFilters,
scriptedFieldLanguageFilter,
saveIndexPattern,
openFieldEditor,
Expand All @@ -670,6 +634,7 @@ export const Tabs: React.FC<TabsProps> = ({
savedObjectsManagement,
allowedTypes,
relationships,
dataViewMgmtService,
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { Dictionary, countBy, defaults, uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
import { DataView, DataViewField } from '@kbn/data-views-plugin/public';
import { FilterChecked } from '@elastic/eui';
import {
TAB_INDEXED_FIELDS,
TAB_SCRIPTED_FIELDS,
Expand Down Expand Up @@ -126,7 +127,11 @@ export function getPath(field: DataViewField, indexPattern: DataView) {
}

export function convertToEuiFilterOptions(options: string[]) {
return uniq(options).map((option) => {
return uniq(options).map<{
value: string;
name: string;
checked?: FilterChecked;
}>((option) => {
return {
value: option,
name: option,
Expand Down
Loading

0 comments on commit 0308537

Please sign in to comment.