forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
/
use_data_view.tsx
133 lines (125 loc) · 4.75 KB
/
use_data_view.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useCallback, useRef } from 'react';
import type { Subscription } from 'rxjs';
import { useDispatch } from 'react-redux';
import memoizeOne from 'memoize-one';
import type { BrowserField, BrowserFields } from '@kbn/timelines-plugin/common';
import { getCategory } from '@kbn/triggers-actions-ui-plugin/public';
import type { DataViewSpec } from '@kbn/data-views-plugin/public';
import { useKibana } from '../../lib/kibana';
import { sourcererActions } from '../../store/sourcerer';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { getSourcererDataView } from '../sourcerer/get_sourcerer_data_view';
import * as i18n from './translations';
import { useAppToasts } from '../../hooks/use_app_toasts';
export type IndexFieldSearch = (param: {
dataViewId: string;
scopeId?: SourcererScopeName;
needToBeInit?: boolean;
cleanCache?: boolean;
skipScopeUpdate?: boolean;
}) => Promise<void>;
type DangerCastForBrowserFieldsMutation = Record<
string,
Omit<BrowserField, 'fields'> & { fields: Record<string, BrowserField> }
>;
interface DataViewInfo {
/**
* @deprecated use fields list on dataview / "indexPattern"
* about to use browserFields? Reconsider! Maybe you can accomplish
* everything you need via the `fields` property on the data view
* you are working with? Or perhaps you need a description for a
* particular field? Consider using the EcsFlat module from `@kbn/ecs`
*/
browserFields: DangerCastForBrowserFieldsMutation;
}
/**
* HOT Code path where the fields can be 16087 in length or larger. This is
* VERY mutatious on purpose to improve the performance of the transform.
*/
export const getDataViewStateFromIndexFields = memoizeOne(
(_title: string, fields: DataViewSpec['fields']): DataViewInfo => {
// Adds two dangerous casts to allow for mutations within this function
type DangerCastForMutation = Record<string, {}>;
if (fields == null) {
return { browserFields: {} };
} else {
const browserFields: BrowserFields = {};
for (const [name, field] of Object.entries(fields)) {
const category = getCategory(name);
if (browserFields[category] == null) {
(browserFields as DangerCastForMutation)[category] = { fields: {} };
}
const categoryFields = browserFields[category].fields;
if (categoryFields) {
categoryFields[name] = field as BrowserField;
}
}
return { browserFields: browserFields as DangerCastForBrowserFieldsMutation };
}
},
(newArgs, lastArgs) => newArgs[0] === lastArgs[0] && newArgs[1]?.length === lastArgs[1]?.length
);
export const useDataView = (): {
indexFieldsSearch: IndexFieldSearch;
} => {
const { data } = useKibana().services;
const abortCtrl = useRef<Record<string, AbortController>>({});
const searchSubscription$ = useRef<Record<string, Subscription>>({});
const dispatch = useDispatch();
const { addError } = useAppToasts();
const setLoading = useCallback(
({ id, loading }: { id: string; loading: boolean }) => {
dispatch(sourcererActions.setDataViewLoading({ id, loading }));
},
[dispatch]
);
const indexFieldsSearch = useCallback<IndexFieldSearch>(
({
dataViewId,
scopeId = SourcererScopeName.default,
needToBeInit = false,
cleanCache = false,
skipScopeUpdate = false,
}) => {
const asyncSearch = async () => {
try {
abortCtrl.current = {
...abortCtrl.current,
[dataViewId]: new AbortController(),
};
setLoading({ id: dataViewId, loading: true });
const dataView = await getSourcererDataView(dataViewId, data.dataViews, cleanCache);
if (needToBeInit && scopeId && !skipScopeUpdate) {
dispatch(
sourcererActions.setSelectedDataView({
id: scopeId,
selectedDataViewId: dataViewId,
selectedPatterns: dataView.patternList,
})
);
}
dispatch(sourcererActions.setDataView({ ...dataView, loading: false }));
} catch (exc) {
addError(exc?.message, {
title: i18n.ERROR_INDEX_FIELDS_SEARCH,
});
}
};
if (searchSubscription$.current[dataViewId]) {
searchSubscription$.current[dataViewId].unsubscribe();
}
if (abortCtrl.current[dataViewId]) {
abortCtrl.current[dataViewId].abort();
}
return asyncSearch();
},
[setLoading, data.dataViews, dispatch, addError]
);
return { indexFieldsSearch };
};