mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
parent
81de77cacd
commit
3078bfa788
41 changed files with 688 additions and 276 deletions
|
@ -0,0 +1,15 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md)
|
||||
|
||||
## createSearchSource variable
|
||||
|
||||
Deserializes a json string and a set of referenced objects to a `SearchSource` instance. Use this method to re-create the search source serialized using `searchSource.serialize`<!-- -->.
|
||||
|
||||
This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
createSearchSource: (indexPatterns: Pick<import("../../index_patterns/index_patterns").IndexPatternsService, "get" | "clearCache" | "getFieldsForTimePattern" | "getFieldsForWildcard" | "getIds" | "getTitles" | "getFields" | "getCache" | "getDefault" | "make">) => (searchSourceJson: string, references: SavedObjectReference[]) => Promise<SearchSource>
|
||||
```
|
|
@ -102,6 +102,7 @@
|
|||
| [castEsToKbnFieldTypeName](./kibana-plugin-plugins-data-public.castestokbnfieldtypename.md) | Get the KbnFieldType name for an esType string |
|
||||
| [connectToQueryState](./kibana-plugin-plugins-data-public.connecttoquerystate.md) | Helper to setup two-way syncing of global data and a state container |
|
||||
| [createSavedQueryService](./kibana-plugin-plugins-data-public.createsavedqueryservice.md) | |
|
||||
| [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md) | Deserializes a json string and a set of referenced objects to a <code>SearchSource</code> instance. Use this method to re-create the search source serialized using <code>searchSource.serialize</code>.<!-- -->This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service |
|
||||
| [ES\_SEARCH\_STRATEGY](./kibana-plugin-plugins-data-public.es_search_strategy.md) | |
|
||||
| [esFilters](./kibana-plugin-plugins-data-public.esfilters.md) | |
|
||||
| [esKuery](./kibana-plugin-plugins-data-public.eskuery.md) | |
|
||||
|
|
|
@ -38,6 +38,7 @@ export declare class SearchSource
|
|||
| [getParent()](./kibana-plugin-plugins-data-public.searchsource.getparent.md) | | Get the parent of this SearchSource {<!-- -->undefined\|searchSource<!-- -->} |
|
||||
| [getSearchRequestBody()](./kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md) | | |
|
||||
| [onRequestStart(handler)](./kibana-plugin-plugins-data-public.searchsource.onrequeststart.md) | | Add a handler that will be notified whenever requests start |
|
||||
| [serialize()](./kibana-plugin-plugins-data-public.searchsource.serialize.md) | | Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.<!-- -->The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named <code>kibanaSavedObjectMeta.searchSourceJSON.index</code> and <code>kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index</code>.<!-- -->Using <code>createSearchSource</code>, the instance can be re-created. |
|
||||
| [setField(field, value)](./kibana-plugin-plugins-data-public.searchsource.setfield.md) | | |
|
||||
| [setFields(newFields)](./kibana-plugin-plugins-data-public.searchsource.setfields.md) | | |
|
||||
| [setParent(parent, options)](./kibana-plugin-plugins-data-public.searchsource.setparent.md) | | Set a searchSource that this source should inherit from |
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [serialize](./kibana-plugin-plugins-data-public.searchsource.serialize.md)
|
||||
|
||||
## SearchSource.serialize() method
|
||||
|
||||
Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.
|
||||
|
||||
The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named `kibanaSavedObjectMeta.searchSourceJSON.index` and `kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index`<!-- -->.
|
||||
|
||||
Using `createSearchSource`<!-- -->, the instance can be re-created.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
serialize(): {
|
||||
searchSourceJSON: string;
|
||||
references: SavedObjectReference[];
|
||||
};
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
`{
|
||||
searchSourceJSON: string;
|
||||
references: SavedObjectReference[];
|
||||
}`
|
||||
|
|
@ -72,6 +72,7 @@ export async function buildServices(
|
|||
const services = {
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
indexPatterns: plugins.data.indexPatterns,
|
||||
search: plugins.data.search,
|
||||
chrome: core.chrome,
|
||||
overlays: core.overlays,
|
||||
};
|
||||
|
|
|
@ -56,6 +56,7 @@ export const savedObjectManagementRegistry: ISavedObjectsManagementRegistry = {
|
|||
const services = {
|
||||
savedObjectsClient: npStart.core.savedObjects.client,
|
||||
indexPatterns: npStart.plugins.data.indexPatterns,
|
||||
search: npStart.plugins.data.search,
|
||||
chrome: npStart.core.chrome,
|
||||
overlays: npStart.core.overlays,
|
||||
};
|
||||
|
|
|
@ -519,7 +519,8 @@ describe('Flyout', () => {
|
|||
expect(resolveIndexPatternConflicts).toHaveBeenCalledWith(
|
||||
component.instance().resolutions,
|
||||
mockConflictedIndexPatterns,
|
||||
true
|
||||
true,
|
||||
defaultProps.indexPatterns
|
||||
);
|
||||
expect(saveObjects).toHaveBeenCalledWith(
|
||||
mockConflictedSavedObjectsLinkedToSavedSearches,
|
||||
|
|
|
@ -358,7 +358,8 @@ export class Flyout extends Component {
|
|||
importCount += await resolveIndexPatternConflicts(
|
||||
resolutions,
|
||||
conflictedIndexPatterns,
|
||||
isOverwriteAllChecked
|
||||
isOverwriteAllChecked,
|
||||
this.props.indexPatterns
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
|
|
|
@ -84,7 +84,7 @@ describe('resolveSavedObjects', () => {
|
|||
},
|
||||
} as unknown) as IndexPatternsContract;
|
||||
|
||||
const services = [
|
||||
const services = ([
|
||||
{
|
||||
type: 'search',
|
||||
get: async () => {
|
||||
|
@ -124,7 +124,7 @@ describe('resolveSavedObjects', () => {
|
|||
};
|
||||
},
|
||||
},
|
||||
] as SavedObjectLoader[];
|
||||
] as unknown) as SavedObjectLoader[];
|
||||
|
||||
const overwriteAll = false;
|
||||
|
||||
|
@ -176,7 +176,7 @@ describe('resolveSavedObjects', () => {
|
|||
},
|
||||
} as unknown) as IndexPatternsContract;
|
||||
|
||||
const services = [
|
||||
const services = ([
|
||||
{
|
||||
type: 'search',
|
||||
get: async () => {
|
||||
|
@ -217,7 +217,7 @@ describe('resolveSavedObjects', () => {
|
|||
};
|
||||
},
|
||||
},
|
||||
] as SavedObjectLoader[];
|
||||
] as unknown) as SavedObjectLoader[];
|
||||
|
||||
const overwriteAll = false;
|
||||
|
||||
|
@ -237,33 +237,38 @@ describe('resolveSavedObjects', () => {
|
|||
|
||||
describe('resolveIndexPatternConflicts', () => {
|
||||
it('should resave resolutions', async () => {
|
||||
const hydrateIndexPattern = jest.fn();
|
||||
const save = jest.fn();
|
||||
|
||||
const conflictedIndexPatterns = [
|
||||
const conflictedIndexPatterns = ([
|
||||
{
|
||||
obj: {
|
||||
searchSource: {
|
||||
getOwnField: (field: string) => {
|
||||
return field === 'index' ? '1' : undefined;
|
||||
save,
|
||||
},
|
||||
doc: {
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: JSON.stringify({
|
||||
index: '1',
|
||||
}),
|
||||
},
|
||||
},
|
||||
hydrateIndexPattern,
|
||||
save,
|
||||
},
|
||||
},
|
||||
{
|
||||
obj: {
|
||||
searchSource: {
|
||||
getOwnField: (field: string) => {
|
||||
return field === 'index' ? '3' : undefined;
|
||||
},
|
||||
},
|
||||
hydrateIndexPattern,
|
||||
save,
|
||||
},
|
||||
doc: {
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: JSON.stringify({
|
||||
index: '3',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
] as unknown) as Array<{ obj: SavedObject; doc: any }>;
|
||||
|
||||
const resolutions = [
|
||||
{
|
||||
|
@ -282,43 +287,49 @@ describe('resolveSavedObjects', () => {
|
|||
|
||||
const overwriteAll = false;
|
||||
|
||||
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll);
|
||||
expect(hydrateIndexPattern.mock.calls.length).toBe(2);
|
||||
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll, ({
|
||||
get: (id: string) => Promise.resolve({ id }),
|
||||
} as unknown) as IndexPatternsContract);
|
||||
expect(conflictedIndexPatterns[0].obj.searchSource!.getField('index')!.id).toEqual('2');
|
||||
expect(conflictedIndexPatterns[1].obj.searchSource!.getField('index')!.id).toEqual('4');
|
||||
expect(save.mock.calls.length).toBe(2);
|
||||
expect(save).toHaveBeenCalledWith({ confirmOverwrite: !overwriteAll });
|
||||
expect(hydrateIndexPattern).toHaveBeenCalledWith('2');
|
||||
expect(hydrateIndexPattern).toHaveBeenCalledWith('4');
|
||||
});
|
||||
|
||||
it('should resolve filter index conflicts', async () => {
|
||||
const hydrateIndexPattern = jest.fn();
|
||||
const save = jest.fn();
|
||||
|
||||
const conflictedIndexPatterns = [
|
||||
const conflictedIndexPatterns = ([
|
||||
{
|
||||
obj: {
|
||||
searchSource: {
|
||||
getOwnField: (field: string) => {
|
||||
return field === 'index' ? '1' : [{ meta: { index: 'filterIndex' } }];
|
||||
},
|
||||
setField: jest.fn(),
|
||||
},
|
||||
hydrateIndexPattern,
|
||||
save,
|
||||
},
|
||||
doc: {
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: JSON.stringify({
|
||||
index: '1',
|
||||
filter: [{ meta: { index: 'filterIndex' } }],
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
obj: {
|
||||
searchSource: {
|
||||
getOwnField: (field: string) => {
|
||||
return field === 'index' ? '3' : undefined;
|
||||
},
|
||||
},
|
||||
hydrateIndexPattern,
|
||||
save,
|
||||
},
|
||||
doc: {
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: JSON.stringify({
|
||||
index: '3',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
] as unknown) as Array<{ obj: SavedObject; doc: any }>;
|
||||
|
||||
const resolutions = [
|
||||
{
|
||||
|
@ -337,9 +348,11 @@ describe('resolveSavedObjects', () => {
|
|||
|
||||
const overwriteAll = false;
|
||||
|
||||
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll);
|
||||
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll, ({
|
||||
get: (id: string) => Promise.resolve({ id }),
|
||||
} as unknown) as IndexPatternsContract);
|
||||
|
||||
expect(conflictedIndexPatterns[0].obj.searchSource.setField).toHaveBeenCalledWith('filter', [
|
||||
expect(conflictedIndexPatterns[0].obj.searchSource!.getField('filter')).toEqual([
|
||||
{ meta: { index: 'newFilterIndex' } },
|
||||
]);
|
||||
expect(save.mock.calls.length).toBe(2);
|
||||
|
|
|
@ -18,12 +18,17 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { OverlayStart } from 'src/core/public';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { OverlayStart, SavedObjectReference } from 'src/core/public';
|
||||
import {
|
||||
SavedObject,
|
||||
SavedObjectLoader,
|
||||
} from '../../../../../../../../plugins/saved_objects/public';
|
||||
import { IndexPatternsContract, IIndexPattern } from '../../../../../../../../plugins/data/public';
|
||||
import {
|
||||
IndexPatternsContract,
|
||||
IIndexPattern,
|
||||
createSearchSource,
|
||||
} from '../../../../../../../../plugins/data/public';
|
||||
|
||||
type SavedObjectsRawDoc = Record<string, any>;
|
||||
|
||||
|
@ -126,7 +131,7 @@ async function importIndexPattern(
|
|||
async function importDocument(obj: SavedObject, doc: SavedObjectsRawDoc, overwriteAll: boolean) {
|
||||
await obj.applyESResp({
|
||||
references: doc._references || [],
|
||||
...doc,
|
||||
...cloneDeep(doc),
|
||||
});
|
||||
return await obj.save({ confirmOverwrite: !overwriteAll });
|
||||
}
|
||||
|
@ -160,41 +165,57 @@ async function awaitEachItemInParallel<T, R>(list: T[], op: (item: T) => R) {
|
|||
export async function resolveIndexPatternConflicts(
|
||||
resolutions: Array<{ oldId: string; newId: string }>,
|
||||
conflictedIndexPatterns: any[],
|
||||
overwriteAll: boolean
|
||||
overwriteAll: boolean,
|
||||
indexPatterns: IndexPatternsContract
|
||||
) {
|
||||
let importCount = 0;
|
||||
|
||||
await awaitEachItemInParallel(conflictedIndexPatterns, async ({ obj }) => {
|
||||
// Resolve search index reference:
|
||||
let oldIndexId = obj.searchSource.getOwnField('index');
|
||||
// Depending on the object, this can either be the raw id or the actual index pattern object
|
||||
if (typeof oldIndexId !== 'string') {
|
||||
oldIndexId = oldIndexId.id;
|
||||
}
|
||||
let resolution = resolutions.find(({ oldId }) => oldId === oldIndexId);
|
||||
if (resolution) {
|
||||
const newIndexId = resolution.newId;
|
||||
await obj.hydrateIndexPattern(newIndexId);
|
||||
await awaitEachItemInParallel(conflictedIndexPatterns, async ({ obj, doc }) => {
|
||||
const serializedSearchSource = JSON.parse(
|
||||
doc._source.kibanaSavedObjectMeta?.searchSourceJSON || '{}'
|
||||
);
|
||||
const oldIndexId = serializedSearchSource.index;
|
||||
let allResolved = true;
|
||||
const inlineResolution = resolutions.find(({ oldId }) => oldId === oldIndexId);
|
||||
if (inlineResolution) {
|
||||
serializedSearchSource.index = inlineResolution.newId;
|
||||
} else {
|
||||
allResolved = false;
|
||||
}
|
||||
|
||||
// Resolve filter index reference:
|
||||
const filter = (obj.searchSource.getOwnField('filter') || []).map((f: any) => {
|
||||
const filter = (serializedSearchSource.filter || []).map((f: any) => {
|
||||
if (!(f.meta && f.meta.index)) {
|
||||
return f;
|
||||
}
|
||||
|
||||
resolution = resolutions.find(({ oldId }) => oldId === f.meta.index);
|
||||
const resolution = resolutions.find(({ oldId }) => oldId === f.meta.index);
|
||||
return resolution ? { ...f, ...{ meta: { ...f.meta, index: resolution.newId } } } : f;
|
||||
});
|
||||
|
||||
if (filter.length > 0) {
|
||||
obj.searchSource.setField('filter', filter);
|
||||
serializedSearchSource.filter = filter;
|
||||
}
|
||||
|
||||
if (!resolution) {
|
||||
const replacedReferences = (doc._references || []).map((reference: SavedObjectReference) => {
|
||||
const resolution = resolutions.find(({ oldId }) => oldId === reference.id);
|
||||
if (resolution) {
|
||||
return { ...reference, id: resolution.newId };
|
||||
} else {
|
||||
allResolved = false;
|
||||
}
|
||||
|
||||
return reference;
|
||||
});
|
||||
|
||||
if (!allResolved) {
|
||||
// The user decided to skip this conflict so do nothing
|
||||
return;
|
||||
}
|
||||
obj.searchSource = await createSearchSource(indexPatterns)(
|
||||
JSON.stringify(serializedSearchSource),
|
||||
replacedReferences
|
||||
);
|
||||
if (await saveObject(obj, overwriteAll)) {
|
||||
importCount++;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ const getResolvedResults = deps => {
|
|||
return createSavedSearchesLoader({
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
indexPatterns: data.indexPatterns,
|
||||
search: data.search,
|
||||
chrome: core.chrome,
|
||||
overlays: core.overlays,
|
||||
}).get(results.vis.data.savedSearchId);
|
||||
|
|
|
@ -28,6 +28,7 @@ const savedObjectsClient = npStart.core.savedObjects.client;
|
|||
const services = {
|
||||
savedObjectsClient,
|
||||
indexPatterns: npStart.plugins.data.indexPatterns,
|
||||
search: npStart.plugins.data.search,
|
||||
chrome: npStart.core.chrome,
|
||||
overlays: npStart.core.overlays,
|
||||
};
|
||||
|
|
|
@ -72,9 +72,11 @@ export function setStartServices(npStart: NpStart) {
|
|||
visualizationsServices.setAggs(npStart.plugins.data.search.aggs);
|
||||
visualizationsServices.setOverlays(npStart.core.overlays);
|
||||
visualizationsServices.setChrome(npStart.core.chrome);
|
||||
visualizationsServices.setSearch(npStart.plugins.data.search);
|
||||
const savedVisualizationsLoader = createSavedVisLoader({
|
||||
savedObjectsClient: npStart.core.savedObjects.client,
|
||||
indexPatterns: npStart.plugins.data.indexPatterns,
|
||||
search: npStart.plugins.data.search,
|
||||
chrome: npStart.core.chrome,
|
||||
overlays: npStart.core.overlays,
|
||||
visualizationTypes: visualizationsServices.getTypes(),
|
||||
|
|
|
@ -284,7 +284,7 @@ export class DashboardPlugin
|
|||
const { notifications } = core;
|
||||
const {
|
||||
uiActions,
|
||||
data: { indexPatterns },
|
||||
data: { indexPatterns, search },
|
||||
} = plugins;
|
||||
|
||||
const SavedObjectFinder = getSavedObjectFinder(core.savedObjects, core.uiSettings);
|
||||
|
@ -300,6 +300,7 @@ export class DashboardPlugin
|
|||
const savedDashboardLoader = createSavedDashboardLoader({
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
indexPatterns,
|
||||
search,
|
||||
chrome: core.chrome,
|
||||
overlays: core.overlays,
|
||||
});
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
*/
|
||||
|
||||
import { SavedObjectsClientContract, ChromeStart, OverlayStart } from 'kibana/public';
|
||||
import { IndexPatternsContract } from '../../../../plugins/data/public';
|
||||
import { DataPublicPluginStart, IndexPatternsContract } from '../../../../plugins/data/public';
|
||||
import { SavedObjectLoader } from '../../../../plugins/saved_objects/public';
|
||||
import { createSavedDashboardClass } from './saved_dashboard';
|
||||
|
||||
interface Services {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
indexPatterns: IndexPatternsContract;
|
||||
search: DataPublicPluginStart['search'];
|
||||
chrome: ChromeStart;
|
||||
overlays: OverlayStart;
|
||||
}
|
||||
|
|
|
@ -366,6 +366,7 @@ export {
|
|||
SearchStrategyProvider,
|
||||
ISearchSource,
|
||||
SearchSource,
|
||||
createSearchSource,
|
||||
SearchSourceFields,
|
||||
EsQuerySortValue,
|
||||
SortDirection,
|
||||
|
|
|
@ -155,7 +155,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
|
|||
const query = this.queryService.start(savedObjects);
|
||||
setQueryService(query);
|
||||
|
||||
const search = this.searchService.start(core);
|
||||
const search = this.searchService.start(core, indexPatterns);
|
||||
setSearchService(search);
|
||||
|
||||
uiActions.attachAction(APPLY_FILTER_TRIGGER, uiActions.getAction(ACTION_GLOBAL_APPLY_FILTER));
|
||||
|
|
|
@ -45,6 +45,7 @@ import * as React_2 from 'react';
|
|||
import { Required } from '@kbn/utility-types';
|
||||
import * as Rx from 'rxjs';
|
||||
import { SavedObject as SavedObject_2 } from 'src/core/public';
|
||||
import { SavedObjectReference } from 'kibana/public';
|
||||
import { SavedObjectsClientContract } from 'src/core/public';
|
||||
import { SearchParams } from 'elasticsearch';
|
||||
import { SearchResponse as SearchResponse_2 } from 'elasticsearch';
|
||||
|
@ -209,6 +210,9 @@ export const connectToQueryState: <S extends QueryState>({ timefilter: { timefil
|
|||
// @public (undocumented)
|
||||
export const createSavedQueryService: (savedObjectsClient: Pick<import("../../../../../core/public").SavedObjectsClient, "update" | "find" | "get" | "delete" | "create" | "bulkCreate" | "bulkGet" | "bulkUpdate">) => SavedQueryService;
|
||||
|
||||
// @public
|
||||
export const createSearchSource: (indexPatterns: Pick<import("../../index_patterns/index_patterns").IndexPatternsService, "get" | "clearCache" | "getFieldsForTimePattern" | "getFieldsForWildcard" | "getIds" | "getTitles" | "getFields" | "getCache" | "getDefault" | "make">) => (searchSourceJson: string, references: SavedObjectReference[]) => Promise<SearchSource>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "CustomFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
|
@ -1677,6 +1681,10 @@ export class SearchSource {
|
|||
// (undocumented)
|
||||
history: SearchRequest[];
|
||||
onRequestStart(handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise<unknown>): void;
|
||||
serialize(): {
|
||||
searchSourceJSON: string;
|
||||
references: SavedObjectReference[];
|
||||
};
|
||||
// (undocumented)
|
||||
setField<K extends keyof SearchSourceFields>(field: K, value: SearchSourceFields[K]): this;
|
||||
// (undocumented)
|
||||
|
@ -1891,21 +1899,21 @@ export type TSearchStrategyProvider<T extends TStrategyTypes> = (context: ISearc
|
|||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromEvent" needs to be exported by the entry point index.d.ts
|
||||
|
|
|
@ -54,6 +54,7 @@ export {
|
|||
SearchSourceFields,
|
||||
EsQuerySortValue,
|
||||
SortDirection,
|
||||
createSearchSource,
|
||||
} from './search_source';
|
||||
|
||||
export { SearchInterceptor } from './search_interceptor';
|
||||
|
|
|
@ -33,6 +33,7 @@ export const searchStartMock: jest.Mocked<ISearchStart> = {
|
|||
aggs: searchAggsStartMock(),
|
||||
setInterceptor: jest.fn(),
|
||||
search: jest.fn(),
|
||||
createSearchSource: jest.fn(),
|
||||
__LEGACY: {
|
||||
AggConfig: jest.fn() as any,
|
||||
AggType: jest.fn(),
|
||||
|
|
|
@ -25,6 +25,8 @@ import { TStrategyTypes } from './strategy_types';
|
|||
import { getEsClient, LegacyApiCaller } from './es_client';
|
||||
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
import { esSearchStrategyProvider } from './es_search/es_search_strategy';
|
||||
import { IndexPatternsContract } from '../index_patterns/index_patterns';
|
||||
import { createSearchSource } from './search_source';
|
||||
import { QuerySetup } from '../query/query_service';
|
||||
import { GetInternalStartServicesFn } from '../types';
|
||||
import { SearchInterceptor } from './search_interceptor';
|
||||
|
@ -108,7 +110,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
};
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ISearchStart {
|
||||
public start(core: CoreStart, indexPatterns: IndexPatternsContract): ISearchStart {
|
||||
/**
|
||||
* A global object that intercepts all searches and provides convenience methods for cancelling
|
||||
* all pending search requests, as well as getting the number of pending search requests.
|
||||
|
@ -145,6 +147,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
// TODO: should an intercepror have a destroy method?
|
||||
this.searchInterceptor = searchInterceptor;
|
||||
},
|
||||
createSearchSource: createSearchSource(indexPatterns),
|
||||
__LEGACY: {
|
||||
esClient: this.esClient!,
|
||||
AggConfig,
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { createSearchSource as createSearchSourceFactory } from './create_search_source';
|
||||
import { IIndexPattern } from '../../../common/index_patterns';
|
||||
import { IndexPatternsContract } from '../../index_patterns/index_patterns';
|
||||
import { Filter } from '../../../common/es_query/filters';
|
||||
|
||||
describe('createSearchSource', function() {
|
||||
let createSearchSource: ReturnType<typeof createSearchSourceFactory>;
|
||||
const indexPatternMock: IIndexPattern = {} as IIndexPattern;
|
||||
let indexPatternContractMock: jest.Mocked<IndexPatternsContract>;
|
||||
|
||||
beforeEach(() => {
|
||||
indexPatternContractMock = ({
|
||||
get: jest.fn().mockReturnValue(Promise.resolve(indexPatternMock)),
|
||||
} as unknown) as jest.Mocked<IndexPatternsContract>;
|
||||
createSearchSource = createSearchSourceFactory(indexPatternContractMock);
|
||||
});
|
||||
|
||||
it('should fail if JSON is invalid', () => {
|
||||
expect(createSearchSource('{', [])).rejects.toThrow();
|
||||
expect(createSearchSource('0', [])).rejects.toThrow();
|
||||
expect(createSearchSource('"abcdefg"', [])).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('should set fields', async () => {
|
||||
const searchSource = await createSearchSource(
|
||||
JSON.stringify({
|
||||
highlightAll: true,
|
||||
query: {
|
||||
query: '',
|
||||
language: 'kuery',
|
||||
},
|
||||
}),
|
||||
[]
|
||||
);
|
||||
expect(searchSource.getOwnField('highlightAll')).toBe(true);
|
||||
expect(searchSource.getOwnField('query')).toEqual({
|
||||
query: '',
|
||||
language: 'kuery',
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve referenced index pattern', async () => {
|
||||
const searchSource = await createSearchSource(
|
||||
JSON.stringify({
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||
}),
|
||||
[
|
||||
{
|
||||
id: '123-456',
|
||||
type: 'index-pattern',
|
||||
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||
},
|
||||
]
|
||||
);
|
||||
expect(indexPatternContractMock.get).toHaveBeenCalledWith('123-456');
|
||||
expect(searchSource.getOwnField('index')).toBe(indexPatternMock);
|
||||
});
|
||||
|
||||
it('should set filters and resolve referenced index patterns', async () => {
|
||||
const searchSource = await createSearchSource(
|
||||
JSON.stringify({
|
||||
filter: [
|
||||
{
|
||||
meta: {
|
||||
alias: null,
|
||||
negate: false,
|
||||
disabled: false,
|
||||
type: 'phrase',
|
||||
key: 'category.keyword',
|
||||
params: {
|
||||
query: "Men's Clothing",
|
||||
},
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
|
||||
},
|
||||
query: {
|
||||
match_phrase: {
|
||||
'category.keyword': "Men's Clothing",
|
||||
},
|
||||
},
|
||||
$state: {
|
||||
store: 'appState',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
[
|
||||
{
|
||||
id: '123-456',
|
||||
type: 'index-pattern',
|
||||
name: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
|
||||
},
|
||||
]
|
||||
);
|
||||
const filters = searchSource.getOwnField('filter') as Filter[];
|
||||
expect(filters[0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"$state": Object {
|
||||
"store": "appState",
|
||||
},
|
||||
"meta": Object {
|
||||
"alias": null,
|
||||
"disabled": false,
|
||||
"index": "123-456",
|
||||
"key": "category.keyword",
|
||||
"negate": false,
|
||||
"params": Object {
|
||||
"query": "Men's Clothing",
|
||||
},
|
||||
"type": "phrase",
|
||||
},
|
||||
"query": Object {
|
||||
"match_phrase": Object {
|
||||
"category.keyword": "Men's Clothing",
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should migrate legacy queries on the fly', async () => {
|
||||
const searchSource = await createSearchSource(
|
||||
JSON.stringify({
|
||||
highlightAll: true,
|
||||
query: 'a:b',
|
||||
}),
|
||||
[]
|
||||
);
|
||||
expect(searchSource.getOwnField('query')).toEqual({
|
||||
query: 'a:b',
|
||||
language: 'lucene',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import _ from 'lodash';
|
||||
import { SavedObjectReference } from 'kibana/public';
|
||||
import { migrateLegacyQuery } from '../../../../kibana_legacy/public';
|
||||
import { InvalidJSONProperty } from '../../../../kibana_utils/public';
|
||||
import { SearchSource } from './search_source';
|
||||
import { IndexPatternsContract } from '../../index_patterns/index_patterns';
|
||||
import { SearchSourceFields } from './types';
|
||||
|
||||
/**
|
||||
* Deserializes a json string and a set of referenced objects to a `SearchSource` instance.
|
||||
* Use this method to re-create the search source serialized using `searchSource.serialize`.
|
||||
*
|
||||
* This function is a factory function that returns the actual utility when calling it with the
|
||||
* required service dependency (index patterns contract). A pre-wired version is also exposed in
|
||||
* the start contract of the data plugin as part of the search service
|
||||
*
|
||||
* @param indexPatterns The index patterns contract of the data plugin
|
||||
*
|
||||
* @return Wired utility function taking two parameters `searchSourceJson`, the json string
|
||||
* returned by `serializeSearchSource` and `references`, a list of references including the ones
|
||||
* returned by `serializeSearchSource`.
|
||||
*
|
||||
* @public */
|
||||
export const createSearchSource = (indexPatterns: IndexPatternsContract) => async (
|
||||
searchSourceJson: string,
|
||||
references: SavedObjectReference[]
|
||||
) => {
|
||||
const searchSource = new SearchSource();
|
||||
|
||||
// if we have a searchSource, set its values based on the searchSourceJson field
|
||||
let searchSourceValues: Record<string, unknown>;
|
||||
try {
|
||||
searchSourceValues = JSON.parse(searchSourceJson);
|
||||
} catch (e) {
|
||||
throw new InvalidJSONProperty(
|
||||
`Invalid JSON in search source. ${e.message} JSON: ${searchSourceJson}`
|
||||
);
|
||||
}
|
||||
|
||||
// This detects a scenario where documents with invalid JSON properties have been imported into the saved object index.
|
||||
// (This happened in issue #20308)
|
||||
if (!searchSourceValues || typeof searchSourceValues !== 'object') {
|
||||
throw new InvalidJSONProperty('Invalid JSON in search source.');
|
||||
}
|
||||
|
||||
// Inject index id if a reference is saved
|
||||
if (searchSourceValues.indexRefName) {
|
||||
const reference = references.find(ref => ref.name === searchSourceValues.indexRefName);
|
||||
if (!reference) {
|
||||
throw new Error(`Could not find reference for ${searchSourceValues.indexRefName}`);
|
||||
}
|
||||
searchSourceValues.index = reference.id;
|
||||
delete searchSourceValues.indexRefName;
|
||||
}
|
||||
|
||||
if (searchSourceValues.filter && Array.isArray(searchSourceValues.filter)) {
|
||||
searchSourceValues.filter.forEach((filterRow: any) => {
|
||||
if (!filterRow.meta || !filterRow.meta.indexRefName) {
|
||||
return;
|
||||
}
|
||||
const reference = references.find((ref: any) => ref.name === filterRow.meta.indexRefName);
|
||||
if (!reference) {
|
||||
throw new Error(`Could not find reference for ${filterRow.meta.indexRefName}`);
|
||||
}
|
||||
filterRow.meta.index = reference.id;
|
||||
delete filterRow.meta.indexRefName;
|
||||
});
|
||||
}
|
||||
|
||||
if (searchSourceValues.index && typeof searchSourceValues.index === 'string') {
|
||||
searchSourceValues.index = await indexPatterns.get(searchSourceValues.index);
|
||||
}
|
||||
|
||||
const searchSourceFields = searchSource.getFields();
|
||||
const fnProps = _.transform(
|
||||
searchSourceFields,
|
||||
function(dynamic, val, name) {
|
||||
if (_.isFunction(val) && name) dynamic[name] = val;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
// This assignment might hide problems because the type of values passed from the parsed JSON
|
||||
// might not fit the SearchSourceFields interface.
|
||||
const newFields: SearchSourceFields = _.defaults(searchSourceValues, fnProps);
|
||||
|
||||
searchSource.setFields(newFields);
|
||||
const query = searchSource.getOwnField('query');
|
||||
|
||||
if (typeof query !== 'undefined') {
|
||||
searchSource.setField('query', migrateLegacyQuery(query));
|
||||
}
|
||||
|
||||
return searchSource;
|
||||
};
|
|
@ -18,4 +18,5 @@
|
|||
*/
|
||||
|
||||
export * from './search_source';
|
||||
export { createSearchSource } from './create_search_source';
|
||||
export { SortDirection, EsQuerySortValue, SearchSourceFields } from './types';
|
||||
|
|
|
@ -37,4 +37,5 @@ export const searchSourceMock: MockedKeys<ISearchSource> = {
|
|||
getSearchRequestBody: jest.fn(),
|
||||
destroy: jest.fn(),
|
||||
history: [],
|
||||
serialize: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { SearchSource } from './search_source';
|
||||
import { IndexPattern } from '../..';
|
||||
import { IndexPattern, SortDirection } from '../..';
|
||||
import { mockDataServices } from '../aggs/test_helpers';
|
||||
|
||||
jest.mock('../fetch', () => ({
|
||||
|
@ -150,4 +150,77 @@ describe('SearchSource', function() {
|
|||
expect(parentFn).toBeCalledWith(searchSource, options);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#serialize', function() {
|
||||
it('should reference index patterns', () => {
|
||||
const indexPattern123 = { id: '123' } as IndexPattern;
|
||||
const searchSource = new SearchSource();
|
||||
searchSource.setField('index', indexPattern123);
|
||||
const { searchSourceJSON, references } = searchSource.serialize();
|
||||
expect(references[0].id).toEqual('123');
|
||||
expect(references[0].type).toEqual('index-pattern');
|
||||
expect(JSON.parse(searchSourceJSON).indexRefName).toEqual(references[0].name);
|
||||
});
|
||||
|
||||
it('should add other fields', () => {
|
||||
const searchSource = new SearchSource();
|
||||
searchSource.setField('highlightAll', true);
|
||||
searchSource.setField('from', 123456);
|
||||
const { searchSourceJSON } = searchSource.serialize();
|
||||
expect(JSON.parse(searchSourceJSON).highlightAll).toEqual(true);
|
||||
expect(JSON.parse(searchSourceJSON).from).toEqual(123456);
|
||||
});
|
||||
|
||||
it('should omit sort and size', () => {
|
||||
const searchSource = new SearchSource();
|
||||
searchSource.setField('highlightAll', true);
|
||||
searchSource.setField('from', 123456);
|
||||
searchSource.setField('sort', { field: SortDirection.asc });
|
||||
searchSource.setField('size', 200);
|
||||
const { searchSourceJSON } = searchSource.serialize();
|
||||
expect(Object.keys(JSON.parse(searchSourceJSON))).toEqual(['highlightAll', 'from']);
|
||||
});
|
||||
|
||||
it('should serialize filters', () => {
|
||||
const searchSource = new SearchSource();
|
||||
const filter = [
|
||||
{
|
||||
query: 'query',
|
||||
meta: {
|
||||
alias: 'alias',
|
||||
disabled: false,
|
||||
negate: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
searchSource.setField('filter', filter);
|
||||
const { searchSourceJSON } = searchSource.serialize();
|
||||
expect(JSON.parse(searchSourceJSON).filter).toEqual(filter);
|
||||
});
|
||||
|
||||
it('should reference index patterns in filters separately from index field', () => {
|
||||
const searchSource = new SearchSource();
|
||||
const indexPattern123 = { id: '123' } as IndexPattern;
|
||||
searchSource.setField('index', indexPattern123);
|
||||
const filter = [
|
||||
{
|
||||
query: 'query',
|
||||
meta: {
|
||||
alias: 'alias',
|
||||
disabled: false,
|
||||
negate: false,
|
||||
index: '456',
|
||||
},
|
||||
},
|
||||
];
|
||||
searchSource.setField('filter', filter);
|
||||
const { searchSourceJSON, references } = searchSource.serialize();
|
||||
expect(references[0].id).toEqual('123');
|
||||
expect(references[0].type).toEqual('index-pattern');
|
||||
expect(JSON.parse(searchSourceJSON).indexRefName).toEqual(references[0].name);
|
||||
expect(references[1].id).toEqual('456');
|
||||
expect(references[1].type).toEqual('index-pattern');
|
||||
expect(JSON.parse(searchSourceJSON).filter[0].meta.indexRefName).toEqual(references[1].name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { SavedObjectReference } from 'kibana/public';
|
||||
import { normalizeSortRequest } from './normalize_sort_request';
|
||||
import { filterDocvalueFields } from './filter_docvalue_fields';
|
||||
import { fieldWildcardFilter } from '../../../../kibana_utils/public';
|
||||
|
@ -419,4 +420,85 @@ export class SearchSource {
|
|||
|
||||
return searchRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the instance to a JSON string and a set of referenced objects.
|
||||
* Use this method to get a representation of the search source which can be stored in a saved object.
|
||||
*
|
||||
* The references returned by this function can be mixed with other references in the same object,
|
||||
* however make sure there are no name-collisions. The references will be named `kibanaSavedObjectMeta.searchSourceJSON.index`
|
||||
* and `kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index`.
|
||||
*
|
||||
* Using `createSearchSource`, the instance can be re-created.
|
||||
* @param searchSource The search source to serialize
|
||||
* @public */
|
||||
public serialize() {
|
||||
const references: SavedObjectReference[] = [];
|
||||
|
||||
const {
|
||||
filter: originalFilters,
|
||||
...searchSourceFields
|
||||
}: Omit<SearchSourceFields, 'sort' | 'size'> = _.omit(this.getFields(), ['sort', 'size']);
|
||||
let serializedSearchSourceFields: Omit<SearchSourceFields, 'sort' | 'size' | 'filter'> & {
|
||||
indexRefName?: string;
|
||||
filter?: Array<Omit<Filter, 'meta'> & { meta: Filter['meta'] & { indexRefName?: string } }>;
|
||||
} = searchSourceFields;
|
||||
if (searchSourceFields.index) {
|
||||
const indexId = searchSourceFields.index.id!;
|
||||
const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index';
|
||||
references.push({
|
||||
name: refName,
|
||||
type: 'index-pattern',
|
||||
id: indexId,
|
||||
});
|
||||
serializedSearchSourceFields = {
|
||||
...serializedSearchSourceFields,
|
||||
indexRefName: refName,
|
||||
index: undefined,
|
||||
};
|
||||
}
|
||||
if (originalFilters) {
|
||||
const filters = this.getFilters(originalFilters);
|
||||
serializedSearchSourceFields = {
|
||||
...serializedSearchSourceFields,
|
||||
filter: filters.map((filterRow, i) => {
|
||||
if (!filterRow.meta || !filterRow.meta.index) {
|
||||
return filterRow;
|
||||
}
|
||||
const refName = `kibanaSavedObjectMeta.searchSourceJSON.filter[${i}].meta.index`;
|
||||
references.push({
|
||||
name: refName,
|
||||
type: 'index-pattern',
|
||||
id: filterRow.meta.index,
|
||||
});
|
||||
return {
|
||||
...filterRow,
|
||||
meta: {
|
||||
...filterRow.meta,
|
||||
indexRefName: refName,
|
||||
index: undefined,
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return { searchSourceJSON: JSON.stringify(serializedSearchSourceFields), references };
|
||||
}
|
||||
|
||||
private getFilters(filterField: SearchSourceFields['filter']): Filter[] {
|
||||
if (!filterField) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(filterField)) {
|
||||
return filterField;
|
||||
}
|
||||
|
||||
if (_.isFunction(filterField)) {
|
||||
return this.getFilters(filterField());
|
||||
}
|
||||
|
||||
return [filterField];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { createSearchSource } from './search_source';
|
||||
import { SearchAggsSetup, SearchAggsStart, SearchAggsStartLegacy } from './aggs';
|
||||
import { ISearch, ISearchGeneric } from './i_search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
|
@ -89,5 +90,6 @@ export interface ISearchStart {
|
|||
aggs: SearchAggsStart;
|
||||
setInterceptor: (searchInterceptor: SearchInterceptor) => void;
|
||||
search: ISearchGeneric;
|
||||
createSearchSource: ReturnType<typeof createSearchSource>;
|
||||
__LEGACY: ISearchStartLegacy & SearchAggsStartLegacy;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ export class SavedObjectsPublicPlugin
|
|||
SavedObjectClass: createSavedObjectClass({
|
||||
indexPatterns: data.indexPatterns,
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
search: data.search,
|
||||
chrome: core.chrome,
|
||||
overlays: core.overlays,
|
||||
}),
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
*/
|
||||
import _ from 'lodash';
|
||||
import { EsResponse, SavedObject, SavedObjectConfig } from '../../types';
|
||||
import { parseSearchSource } from './parse_search_source';
|
||||
import { expandShorthand, SavedObjectNotFound } from '../../../../kibana_utils/public';
|
||||
import { IndexPattern } from '../../../../data/public';
|
||||
import { DataPublicPluginStart, IndexPattern } from '../../../../data/public';
|
||||
|
||||
/**
|
||||
* A given response of and ElasticSearch containing a plain saved object is applied to the given
|
||||
|
@ -29,13 +28,13 @@ import { IndexPattern } from '../../../../data/public';
|
|||
export async function applyESResp(
|
||||
resp: EsResponse,
|
||||
savedObject: SavedObject,
|
||||
config: SavedObjectConfig
|
||||
config: SavedObjectConfig,
|
||||
createSearchSource: DataPublicPluginStart['search']['createSearchSource']
|
||||
) {
|
||||
const mapping = expandShorthand(config.mapping);
|
||||
const esType = config.type || '';
|
||||
savedObject._source = _.cloneDeep(resp._source);
|
||||
const injectReferences = config.injectReferences;
|
||||
const hydrateIndexPattern = savedObject.hydrateIndexPattern!;
|
||||
if (typeof resp.found === 'boolean' && !resp.found) {
|
||||
throw new SavedObjectNotFound(esType, savedObject.id || '');
|
||||
}
|
||||
|
@ -64,13 +63,34 @@ export async function applyESResp(
|
|||
_.assign(savedObject, savedObject._source);
|
||||
savedObject.lastSavedTitle = savedObject.title;
|
||||
|
||||
await parseSearchSource(savedObject, esType, meta.searchSourceJSON, resp.references);
|
||||
await hydrateIndexPattern();
|
||||
if (config.searchSource) {
|
||||
try {
|
||||
savedObject.searchSource = await createSearchSource(meta.searchSourceJSON, resp.references);
|
||||
} catch (error) {
|
||||
if (
|
||||
error.constructor.name === 'SavedObjectNotFound' &&
|
||||
error.savedObjectType === 'index-pattern'
|
||||
) {
|
||||
// if parsing the search source fails because the index pattern wasn't found,
|
||||
// remember the reference - this is required for error handling on legacy imports
|
||||
savedObject.unresolvedIndexPatternReference = {
|
||||
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||
id: JSON.parse(meta.searchSourceJSON).index,
|
||||
type: 'index-pattern',
|
||||
};
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
if (injectReferences && resp.references && resp.references.length > 0) {
|
||||
injectReferences(savedObject, resp.references);
|
||||
}
|
||||
|
||||
if (typeof config.afterESResp === 'function') {
|
||||
savedObject = await config.afterESResp(savedObject);
|
||||
}
|
||||
|
||||
return savedObject;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@ export function buildSavedObject(
|
|||
*/
|
||||
savedObject.init = _.once(() => intializeSavedObject(savedObject, savedObjectsClient, config));
|
||||
|
||||
savedObject.applyESResp = (resp: EsResponse) => applyESResp(resp, savedObject, config);
|
||||
savedObject.applyESResp = (resp: EsResponse) =>
|
||||
applyESResp(resp, savedObject, config, services.search.createSearchSource);
|
||||
|
||||
/**
|
||||
* Serialize this object
|
||||
|
|
|
@ -31,25 +31,19 @@ export async function hydrateIndexPattern(
|
|||
indexPatterns: IndexPatternsContract,
|
||||
config: SavedObjectConfig
|
||||
) {
|
||||
const clearSavedIndexPattern = !!config.clearSavedIndexPattern;
|
||||
const indexPattern = config.indexPattern;
|
||||
|
||||
if (!savedObject.searchSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (clearSavedIndexPattern) {
|
||||
savedObject.searchSource!.setField('index', undefined);
|
||||
return null;
|
||||
}
|
||||
|
||||
const index = id || indexPattern || savedObject.searchSource!.getOwnField('index');
|
||||
const index = id || indexPattern || savedObject.searchSource.getOwnField('index');
|
||||
|
||||
if (typeof index !== 'string' || !index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const indexObj = await indexPatterns.get(index);
|
||||
savedObject.searchSource!.setField('index', indexObj);
|
||||
savedObject.searchSource.setField('index', indexObj);
|
||||
return indexObj;
|
||||
}
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import _ from 'lodash';
|
||||
import { migrateLegacyQuery } from '../../../../kibana_legacy/public';
|
||||
import { SavedObject } from '../../types';
|
||||
import { InvalidJSONProperty } from '../../../../kibana_utils/public';
|
||||
|
||||
export function parseSearchSource(
|
||||
savedObject: SavedObject,
|
||||
esType: string,
|
||||
searchSourceJson: string,
|
||||
references: any[]
|
||||
) {
|
||||
if (!savedObject.searchSource) return;
|
||||
|
||||
// if we have a searchSource, set its values based on the searchSourceJson field
|
||||
let searchSourceValues: Record<string, any>;
|
||||
try {
|
||||
searchSourceValues = JSON.parse(searchSourceJson);
|
||||
} catch (e) {
|
||||
throw new InvalidJSONProperty(
|
||||
`Invalid JSON in ${esType} "${savedObject.id}". ${e.message} JSON: ${searchSourceJson}`
|
||||
);
|
||||
}
|
||||
|
||||
// This detects a scenario where documents with invalid JSON properties have been imported into the saved object index.
|
||||
// (This happened in issue #20308)
|
||||
if (!searchSourceValues || typeof searchSourceValues !== 'object') {
|
||||
throw new InvalidJSONProperty(`Invalid searchSourceJSON in ${esType} "${savedObject.id}".`);
|
||||
}
|
||||
|
||||
// Inject index id if a reference is saved
|
||||
if (searchSourceValues.indexRefName) {
|
||||
const reference = references.find(
|
||||
(ref: Record<string, any>) => ref.name === searchSourceValues.indexRefName
|
||||
);
|
||||
if (!reference) {
|
||||
throw new Error(
|
||||
`Could not find reference for ${
|
||||
searchSourceValues.indexRefName
|
||||
} on ${savedObject.getEsType()} ${savedObject.id}`
|
||||
);
|
||||
}
|
||||
searchSourceValues.index = reference.id;
|
||||
delete searchSourceValues.indexRefName;
|
||||
}
|
||||
|
||||
if (searchSourceValues.filter) {
|
||||
searchSourceValues.filter.forEach((filterRow: any) => {
|
||||
if (!filterRow.meta || !filterRow.meta.indexRefName) {
|
||||
return;
|
||||
}
|
||||
const reference = references.find((ref: any) => ref.name === filterRow.meta.indexRefName);
|
||||
if (!reference) {
|
||||
throw new Error(
|
||||
`Could not find reference for ${
|
||||
filterRow.meta.indexRefName
|
||||
} on ${savedObject.getEsType()}`
|
||||
);
|
||||
}
|
||||
filterRow.meta.index = reference.id;
|
||||
delete filterRow.meta.indexRefName;
|
||||
});
|
||||
}
|
||||
|
||||
const searchSourceFields = savedObject.searchSource.getFields();
|
||||
const fnProps = _.transform(
|
||||
searchSourceFields,
|
||||
function(dynamic: Record<string, any>, val: any, name: string | undefined) {
|
||||
if (_.isFunction(val) && name) dynamic[name] = val;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
savedObject.searchSource.setFields(_.defaults(searchSourceValues, fnProps));
|
||||
const query = savedObject.searchSource.getOwnField('query');
|
||||
|
||||
if (typeof query !== 'undefined') {
|
||||
savedObject.searchSource.setField('query', migrateLegacyQuery(query));
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
import _ from 'lodash';
|
||||
import angular from 'angular';
|
||||
import { SavedObject, SavedObjectConfig } from '../../types';
|
||||
import { expandShorthand } from '../../../../kibana_utils/public';
|
||||
|
||||
|
@ -41,57 +40,16 @@ export function serializeSavedObject(savedObject: SavedObject, config: SavedObje
|
|||
});
|
||||
|
||||
if (savedObject.searchSource) {
|
||||
let searchSourceFields: Record<string, any> = _.omit(savedObject.searchSource.getFields(), [
|
||||
'sort',
|
||||
'size',
|
||||
]);
|
||||
if (searchSourceFields.index) {
|
||||
// searchSourceFields.index will normally be an IndexPattern, but can be a string in two scenarios:
|
||||
// (1) `init()` (and by extension `hydrateIndexPattern()`) hasn't been called on Saved Object
|
||||
// (2) The IndexPattern doesn't exist, so we fail to resolve it in `hydrateIndexPattern()`
|
||||
const indexId =
|
||||
typeof searchSourceFields.index === 'string'
|
||||
? searchSourceFields.index
|
||||
: searchSourceFields.index.id;
|
||||
const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index';
|
||||
references.push({
|
||||
name: refName,
|
||||
type: 'index-pattern',
|
||||
id: indexId,
|
||||
});
|
||||
searchSourceFields = {
|
||||
...searchSourceFields,
|
||||
indexRefName: refName,
|
||||
index: undefined,
|
||||
};
|
||||
}
|
||||
if (searchSourceFields.filter) {
|
||||
searchSourceFields = {
|
||||
...searchSourceFields,
|
||||
filter: searchSourceFields.filter.map((filterRow: any, i: number) => {
|
||||
if (!filterRow.meta || !filterRow.meta.index) {
|
||||
return filterRow;
|
||||
}
|
||||
const refName = `kibanaSavedObjectMeta.searchSourceJSON.filter[${i}].meta.index`;
|
||||
references.push({
|
||||
name: refName,
|
||||
type: 'index-pattern',
|
||||
id: filterRow.meta.index,
|
||||
});
|
||||
return {
|
||||
...filterRow,
|
||||
meta: {
|
||||
...filterRow.meta,
|
||||
indexRefName: refName,
|
||||
index: undefined,
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
attributes.kibanaSavedObjectMeta = {
|
||||
searchSourceJSON: angular.toJson(searchSourceFields),
|
||||
};
|
||||
const {
|
||||
searchSourceJSON,
|
||||
references: searchSourceReferences,
|
||||
} = savedObject.searchSource.serialize();
|
||||
attributes.kibanaSavedObjectMeta = { searchSourceJSON };
|
||||
references.push(...searchSourceReferences);
|
||||
}
|
||||
|
||||
if (savedObject.unresolvedIndexPatternReference) {
|
||||
references.push(savedObject.unresolvedIndexPatternReference);
|
||||
}
|
||||
|
||||
return { attributes, references };
|
||||
|
|
|
@ -103,9 +103,11 @@ describe('Saved Object', () => {
|
|||
}
|
||||
|
||||
beforeEach(() => {
|
||||
(dataStartMock.search.createSearchSource as jest.Mock).mockReset();
|
||||
SavedObjectClass = createSavedObjectClass({
|
||||
savedObjectsClient: savedObjectsClientStub,
|
||||
indexPatterns: dataStartMock.indexPatterns,
|
||||
search: dataStartMock.search,
|
||||
} as SavedObjectKibanaServices);
|
||||
});
|
||||
|
||||
|
@ -269,7 +271,7 @@ describe('Saved Object', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('when index exists in searchSourceJSON', () => {
|
||||
it('when search source references saved object', () => {
|
||||
const id = '123';
|
||||
stubESResponse(getMockedDocResponse(id));
|
||||
return createInitializedSavedObject({ type: 'dashboard', searchSource: true }).then(
|
||||
|
@ -409,18 +411,17 @@ describe('Saved Object', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('throws error invalid JSON is detected', async () => {
|
||||
it('forwards thrown exceptions from createSearchSource', async () => {
|
||||
(dataStartMock.search.createSearchSource as jest.Mock).mockImplementation(() => {
|
||||
throw new InvalidJSONProperty('');
|
||||
});
|
||||
const savedObject = await createInitializedSavedObject({
|
||||
type: 'dashboard',
|
||||
searchSource: true,
|
||||
});
|
||||
const response = {
|
||||
found: true,
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: '"{\\n \\"filter\\": []\\n}"',
|
||||
},
|
||||
},
|
||||
_source: {},
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -586,23 +587,24 @@ describe('Saved Object', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('injects references from searchSourceJSON', async () => {
|
||||
it('passes references to search source parsing function', async () => {
|
||||
const savedObject = new SavedObjectClass({ type: 'dashboard', searchSource: true });
|
||||
return savedObject.init!().then(() => {
|
||||
const searchSourceJSON = JSON.stringify({
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||
filter: [
|
||||
{
|
||||
meta: {
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const response = {
|
||||
found: true,
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: JSON.stringify({
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||
filter: [
|
||||
{
|
||||
meta: {
|
||||
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
searchSourceJSON,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
|
@ -619,16 +621,10 @@ describe('Saved Object', () => {
|
|||
],
|
||||
};
|
||||
savedObject.applyESResp(response);
|
||||
expect(savedObject.searchSource!.getFields()).toEqual({
|
||||
index: 'my-index-1',
|
||||
filter: [
|
||||
{
|
||||
meta: {
|
||||
index: 'my-index-2',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(dataStartMock.search.createSearchSource).toBeCalledWith(
|
||||
searchSourceJSON,
|
||||
response.references
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -24,7 +24,12 @@ import {
|
|||
SavedObjectAttributes,
|
||||
SavedObjectReference,
|
||||
} from 'kibana/public';
|
||||
import { IIndexPattern, IndexPatternsContract, ISearchSource } from '../../data/public';
|
||||
import {
|
||||
DataPublicPluginStart,
|
||||
IIndexPattern,
|
||||
IndexPatternsContract,
|
||||
ISearchSource,
|
||||
} from '../../data/public';
|
||||
|
||||
export interface SavedObject {
|
||||
_serialize: () => { attributes: SavedObjectAttributes; references: SavedObjectReference[] };
|
||||
|
@ -49,6 +54,7 @@ export interface SavedObject {
|
|||
searchSource?: ISearchSource;
|
||||
showInRecentlyAccessed: boolean;
|
||||
title: string;
|
||||
unresolvedIndexPatternReference?: SavedObjectReference;
|
||||
}
|
||||
|
||||
export interface SavedObjectSaveOpts {
|
||||
|
@ -65,6 +71,7 @@ export interface SavedObjectCreationOpts {
|
|||
export interface SavedObjectKibanaServices {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
indexPatterns: IndexPatternsContract;
|
||||
search: DataPublicPluginStart['search'];
|
||||
chrome: ChromeStart;
|
||||
overlays: OverlayStart;
|
||||
}
|
||||
|
@ -72,7 +79,6 @@ export interface SavedObjectKibanaServices {
|
|||
export interface SavedObjectConfig {
|
||||
// is only used by visualize
|
||||
afterESResp?: (savedObject: SavedObject) => Promise<SavedObject>;
|
||||
clearSavedIndexPattern?: boolean;
|
||||
defaults?: any;
|
||||
extractReferences?: (opts: {
|
||||
attributes: SavedObjectAttributes;
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
setCapabilities,
|
||||
setHttp,
|
||||
setIndexPatterns,
|
||||
setSearch,
|
||||
setSavedObjects,
|
||||
setUsageCollector,
|
||||
setFilterManager,
|
||||
|
@ -140,6 +141,7 @@ export class VisualizationsPlugin
|
|||
setHttp(core.http);
|
||||
setSavedObjects(core.savedObjects);
|
||||
setIndexPatterns(data.indexPatterns);
|
||||
setSearch(data.search);
|
||||
setFilterManager(data.query.filterManager);
|
||||
setExpressions(expressions);
|
||||
setUiActions(uiActions);
|
||||
|
@ -150,6 +152,7 @@ export class VisualizationsPlugin
|
|||
const savedVisualizationsLoader = createSavedVisLoader({
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
indexPatterns: data.indexPatterns,
|
||||
search: data.search,
|
||||
chrome: core.chrome,
|
||||
overlays: core.overlays,
|
||||
visualizationTypes: types,
|
||||
|
|
|
@ -35,7 +35,7 @@ import { extractReferences, injectReferences } from './saved_visualization_refer
|
|||
import { IIndexPattern, ISearchSource, SearchSource } from '../../../../plugins/data/public';
|
||||
import { ISavedVis, SerializedVis } from '../types';
|
||||
import { createSavedSearchesLoader } from '../../../../plugins/discover/public';
|
||||
import { getChrome, getOverlays, getIndexPatterns, getSavedObjects } from '../services';
|
||||
import { getChrome, getOverlays, getIndexPatterns, getSavedObjects, getSearch } from '../services';
|
||||
|
||||
export const convertToSerializedVis = async (savedVis: ISavedVis): Promise<SerializedVis> => {
|
||||
const { visState } = savedVis;
|
||||
|
@ -87,6 +87,7 @@ const getSearchSource = async (inputSearchSource: ISearchSource, savedSearchId?:
|
|||
const savedSearch = await createSavedSearchesLoader({
|
||||
savedObjectsClient: getSavedObjects().client,
|
||||
indexPatterns: getIndexPatterns(),
|
||||
search: getSearch(),
|
||||
chrome: getChrome(),
|
||||
overlays: getOverlays(),
|
||||
}).get(savedSearchId);
|
||||
|
|
|
@ -63,6 +63,8 @@ export const [getIndexPatterns, setIndexPatterns] = createGetterSetter<IndexPatt
|
|||
'IndexPatterns'
|
||||
);
|
||||
|
||||
export const [getSearch, setSearch] = createGetterSetter<DataPublicPluginStart['search']>('Search');
|
||||
|
||||
export const [getUsageCollector, setUsageCollector] = createGetterSetter<UsageCollectionSetup>(
|
||||
'UsageCollection'
|
||||
);
|
||||
|
|
|
@ -17,6 +17,7 @@ module.service('gisMapSavedObjectLoader', function() {
|
|||
const services = {
|
||||
savedObjectsClient,
|
||||
indexPatterns: npStart.plugins.data.indexPatterns,
|
||||
search: npStart.plugins.data.search,
|
||||
chrome: npStart.core.chrome,
|
||||
overlays: npStart.core.overlays,
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ export const useSearchItems = (defaultSavedObjectId: string | undefined) => {
|
|||
const savedSearches = createSavedSearchesLoader({
|
||||
savedObjectsClient,
|
||||
indexPatterns,
|
||||
search: appDeps.data.search,
|
||||
chrome: appDeps.chrome,
|
||||
overlays: appDeps.overlays,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue