2019-09-17 20:57:53 +02:00
|
|
|
/*
|
|
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
|
|
* or more contributor license agreements. Licensed under the Elastic License;
|
|
|
|
* you may not use this file except in compliance with the Elastic License.
|
|
|
|
*/
|
|
|
|
|
2019-10-09 21:20:55 +02:00
|
|
|
import _ from 'lodash';
|
2020-06-26 16:33:09 +02:00
|
|
|
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
|
2020-08-21 18:08:25 +02:00
|
|
|
import { SavedObjectsClientContract, HttpSetup, SavedObjectReference } from 'kibana/public';
|
2019-10-09 21:20:55 +02:00
|
|
|
import { StateSetter } from '../types';
|
|
|
|
import {
|
|
|
|
IndexPattern,
|
|
|
|
IndexPatternRef,
|
|
|
|
IndexPatternPersistedState,
|
|
|
|
IndexPatternPrivateState,
|
|
|
|
IndexPatternField,
|
2020-08-21 18:08:25 +02:00
|
|
|
IndexPatternLayer,
|
2019-10-09 21:20:55 +02:00
|
|
|
} from './types';
|
2020-11-10 19:45:46 +01:00
|
|
|
import { updateLayerIndexPattern } from './operations';
|
2020-04-15 12:22:37 +02:00
|
|
|
import { DateRange, ExistingFields } from '../../common/types';
|
|
|
|
import { BASE_API_URL } from '../../common';
|
2020-02-12 08:04:51 +01:00
|
|
|
import {
|
2020-08-21 11:33:42 +02:00
|
|
|
IndexPatternsContract,
|
2020-02-12 08:04:51 +01:00
|
|
|
indexPatterns as indexPatternsUtils,
|
2020-04-15 12:22:37 +02:00
|
|
|
} from '../../../../../src/plugins/data/public';
|
2020-10-06 10:15:41 +02:00
|
|
|
import { VisualizeFieldContext } from '../../../../../src/plugins/ui_actions/public';
|
2020-08-21 11:33:42 +02:00
|
|
|
import { documentField } from './document_field';
|
2020-06-26 16:33:09 +02:00
|
|
|
import { readFromStorage, writeToStorage } from '../settings_storage';
|
2020-11-10 14:31:04 +01:00
|
|
|
import { getFieldByNameFactory } from './pure_helpers';
|
2019-09-17 20:57:53 +02:00
|
|
|
|
2019-10-14 18:46:33 +02:00
|
|
|
type SetState = StateSetter<IndexPatternPrivateState>;
|
2020-08-21 11:33:42 +02:00
|
|
|
type SavedObjectsClient = Pick<SavedObjectsClientContract, 'find'>;
|
|
|
|
type IndexPatternsService = Pick<IndexPatternsContract, 'get'>;
|
2019-10-09 21:20:55 +02:00
|
|
|
type ErrorHandler = (err: Error) => void;
|
|
|
|
|
|
|
|
export async function loadIndexPatterns({
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
patterns,
|
|
|
|
cache,
|
|
|
|
}: {
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService: IndexPatternsService;
|
2019-10-09 21:20:55 +02:00
|
|
|
patterns: string[];
|
|
|
|
cache: Record<string, IndexPattern>;
|
|
|
|
}) {
|
2020-05-22 09:08:58 +02:00
|
|
|
const missingIds = patterns.filter((id) => !cache[id]);
|
2019-10-09 21:20:55 +02:00
|
|
|
|
|
|
|
if (missingIds.length === 0) {
|
|
|
|
return cache;
|
|
|
|
}
|
|
|
|
|
2020-08-21 11:33:42 +02:00
|
|
|
const indexPatterns = await Promise.all(missingIds.map((id) => indexPatternsService.get(id)));
|
|
|
|
const indexPatternsObject = indexPatterns.reduce(
|
|
|
|
(acc, indexPattern) => {
|
|
|
|
const newFields = indexPattern.fields
|
|
|
|
.filter(
|
|
|
|
(field) =>
|
|
|
|
!indexPatternsUtils.isNestedField(field) && (!!field.aggregatable || !!field.scripted)
|
|
|
|
)
|
|
|
|
.map(
|
2020-09-08 23:29:26 +02:00
|
|
|
(field): IndexPatternField => {
|
|
|
|
// Convert the getters on the index pattern service into plain JSON
|
|
|
|
const base = {
|
|
|
|
name: field.name,
|
|
|
|
displayName: field.displayName,
|
|
|
|
type: field.type,
|
|
|
|
aggregatable: field.aggregatable,
|
|
|
|
searchable: field.searchable,
|
2020-09-24 09:55:32 +02:00
|
|
|
meta: indexPattern.metaFields.includes(field.name),
|
2020-09-08 23:29:26 +02:00
|
|
|
esTypes: field.esTypes,
|
|
|
|
scripted: field.scripted,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Simplifies tests by hiding optional properties instead of undefined
|
|
|
|
return base.scripted
|
|
|
|
? {
|
|
|
|
...base,
|
|
|
|
lang: field.lang,
|
|
|
|
script: field.script,
|
|
|
|
}
|
|
|
|
: base;
|
|
|
|
}
|
2020-08-21 11:33:42 +02:00
|
|
|
)
|
|
|
|
.concat(documentField);
|
|
|
|
|
|
|
|
const { typeMeta, title, timeFieldName, fieldFormatMap } = indexPattern;
|
|
|
|
if (typeMeta?.aggs) {
|
|
|
|
const aggs = Object.keys(typeMeta.aggs);
|
|
|
|
newFields.forEach((field, index) => {
|
|
|
|
const restrictionsObj: IndexPatternField['aggregationRestrictions'] = {};
|
|
|
|
aggs.forEach((agg) => {
|
|
|
|
const restriction =
|
|
|
|
typeMeta.aggs && typeMeta.aggs[agg] && typeMeta.aggs[agg][field.name];
|
|
|
|
if (restriction) {
|
|
|
|
restrictionsObj[agg] = restriction;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (Object.keys(restrictionsObj).length) {
|
|
|
|
newFields[index] = { ...field, aggregationRestrictions: restrictionsObj };
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2019-10-09 21:20:55 +02:00
|
|
|
|
2020-08-21 11:33:42 +02:00
|
|
|
const currentIndexPattern: IndexPattern = {
|
|
|
|
id: indexPattern.id!, // id exists for sure because we got index patterns by id
|
|
|
|
title,
|
|
|
|
timeFieldName,
|
2020-10-27 18:08:01 +01:00
|
|
|
fieldFormatMap:
|
|
|
|
fieldFormatMap &&
|
|
|
|
Object.fromEntries(
|
|
|
|
Object.entries(fieldFormatMap).map(([id, format]) => [
|
|
|
|
id,
|
|
|
|
'toJSON' in format ? format.toJSON() : format,
|
|
|
|
])
|
|
|
|
),
|
2020-08-21 11:33:42 +02:00
|
|
|
fields: newFields,
|
2020-11-10 14:31:04 +01:00
|
|
|
getFieldByName: getFieldByNameFactory(newFields),
|
2020-08-26 09:09:40 +02:00
|
|
|
hasRestrictions: !!typeMeta?.aggs,
|
2020-08-21 11:33:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return {
|
|
|
|
[currentIndexPattern.id]: currentIndexPattern,
|
|
|
|
...acc,
|
|
|
|
};
|
2019-10-09 21:20:55 +02:00
|
|
|
},
|
|
|
|
{ ...cache }
|
|
|
|
);
|
2020-08-21 11:33:42 +02:00
|
|
|
|
|
|
|
return indexPatternsObject;
|
2019-10-09 21:20:55 +02:00
|
|
|
}
|
|
|
|
|
2020-06-26 16:33:09 +02:00
|
|
|
const getLastUsedIndexPatternId = (
|
|
|
|
storage: IStorageWrapper,
|
|
|
|
indexPatternRefs: IndexPatternRef[]
|
|
|
|
) => {
|
|
|
|
const indexPattern = readFromStorage(storage, 'indexPatternId');
|
|
|
|
return indexPattern && indexPatternRefs.find((i) => i.id === indexPattern)?.id;
|
|
|
|
};
|
|
|
|
|
|
|
|
const setLastUsedIndexPatternId = (storage: IStorageWrapper, value: string) => {
|
|
|
|
writeToStorage(storage, 'indexPatternId', value);
|
|
|
|
};
|
|
|
|
|
2020-08-21 18:08:25 +02:00
|
|
|
const CURRENT_PATTERN_REFERENCE_NAME = 'indexpattern-datasource-current-indexpattern';
|
|
|
|
function getLayerReferenceName(layerId: string) {
|
|
|
|
return `indexpattern-datasource-layer-${layerId}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function extractReferences({ currentIndexPatternId, layers }: IndexPatternPrivateState) {
|
|
|
|
const savedObjectReferences: SavedObjectReference[] = [];
|
|
|
|
savedObjectReferences.push({
|
|
|
|
type: 'index-pattern',
|
|
|
|
id: currentIndexPatternId,
|
|
|
|
name: CURRENT_PATTERN_REFERENCE_NAME,
|
|
|
|
});
|
|
|
|
const persistableLayers: Record<string, Omit<IndexPatternLayer, 'indexPatternId'>> = {};
|
|
|
|
Object.entries(layers).forEach(([layerId, { indexPatternId, ...persistableLayer }]) => {
|
|
|
|
savedObjectReferences.push({
|
|
|
|
type: 'index-pattern',
|
|
|
|
id: indexPatternId,
|
|
|
|
name: getLayerReferenceName(layerId),
|
|
|
|
});
|
|
|
|
persistableLayers[layerId] = persistableLayer;
|
|
|
|
});
|
|
|
|
return { savedObjectReferences, state: { layers: persistableLayers } };
|
|
|
|
}
|
|
|
|
|
|
|
|
export function injectReferences(
|
|
|
|
state: IndexPatternPersistedState,
|
|
|
|
references: SavedObjectReference[]
|
|
|
|
) {
|
|
|
|
const layers: Record<string, IndexPatternLayer> = {};
|
|
|
|
Object.entries(state.layers).forEach(([layerId, persistedLayer]) => {
|
|
|
|
layers[layerId] = {
|
|
|
|
...persistedLayer,
|
|
|
|
indexPatternId: references.find(({ name }) => name === getLayerReferenceName(layerId))!.id,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
currentIndexPatternId: references.find(({ name }) => name === CURRENT_PATTERN_REFERENCE_NAME)!
|
|
|
|
.id,
|
|
|
|
layers,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-10-09 21:20:55 +02:00
|
|
|
export async function loadInitialState({
|
2020-08-21 18:08:25 +02:00
|
|
|
persistedState,
|
|
|
|
references,
|
2019-10-09 21:20:55 +02:00
|
|
|
savedObjectsClient,
|
2020-01-06 20:55:51 +01:00
|
|
|
defaultIndexPatternId,
|
2020-06-26 16:33:09 +02:00
|
|
|
storage,
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2020-10-06 10:15:41 +02:00
|
|
|
initialContext,
|
2019-10-09 21:20:55 +02:00
|
|
|
}: {
|
2020-08-21 18:08:25 +02:00
|
|
|
persistedState?: IndexPatternPersistedState;
|
|
|
|
references?: SavedObjectReference[];
|
2019-10-09 21:20:55 +02:00
|
|
|
savedObjectsClient: SavedObjectsClient;
|
2020-01-06 20:55:51 +01:00
|
|
|
defaultIndexPatternId?: string;
|
2020-06-26 16:33:09 +02:00
|
|
|
storage: IStorageWrapper;
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService: IndexPatternsService;
|
2020-10-06 10:15:41 +02:00
|
|
|
initialContext?: VisualizeFieldContext;
|
2019-10-09 21:20:55 +02:00
|
|
|
}): Promise<IndexPatternPrivateState> {
|
|
|
|
const indexPatternRefs = await loadIndexPatternRefs(savedObjectsClient);
|
2020-06-26 16:33:09 +02:00
|
|
|
const lastUsedIndexPatternId = getLastUsedIndexPatternId(storage, indexPatternRefs);
|
|
|
|
|
2020-08-21 18:08:25 +02:00
|
|
|
const state =
|
|
|
|
persistedState && references ? injectReferences(persistedState, references) : undefined;
|
|
|
|
|
chore(NA): upgrade to lodash@4 (#69868)
* chore(NA): upgrade oss to lodash4
chore(NA): migrate cli, cli_plugin, cli_keystore, dev, test_utils and apm src script to lodash4
chore(NA): missing file for cli plugin
chore(NA): add src core
chore(NA): es archiver and fixtures
chore(NA): try to fix functional test failure
chore(NA): migrate src/legacy entirely to lodash4 except src/legacy/core_plugins
chore(NA): move legacy core plugins to lodash4
chore(NA): upgrade optimize to lodash4
chore(NA): upgrade to lodash4 on advanced_settings, charts, console and dashboard
chore(NA): migrate to lodash4 on dev_tools, discover, embeddable, es_ui)shared, expressions, home plugins
chore(NA): upgrade data plugin to lodash4
chore(NA): upgrade usage_collection, ui_actions, tile_map, telemtry, share, saved_objects, saved_objects_management, region_map and navigation to lodash4
chore(NA): missing data upgrades to lodash4
Revert "chore(NA): upgrade usage_collection, ui_actions, tile_map, telemtry, share, saved_objects, saved_objects_management, region_map and navigation to lodash4"
This reverts commit 137055c5fed2fc52bb26547e0bc1ad2e3d4fe309.
Revert "Revert "chore(NA): upgrade usage_collection, ui_actions, tile_map, telemtry, share, saved_objects, saved_objects_management, region_map and navigation to lodash4""
This reverts commit f7e73688782998513d9fb6d7e8f0765e9beb28d1.
Revert "chore(NA): missing data upgrades to lodash4"
This reverts commit 92b85bf947a89bfc70cc4052738a6b2128ffb076.
Revert "chore(NA): upgrade data plugin to lodash4"
This reverts commit 88fdb075ee1e26c4ac979b6681d8a2b002df74c6.
chore(NA): upgrade idx_pattern_mgt, input_control_vis, inspector, kbn_legacy, kbn_react, kbn_usage_collections, kbn_utils, management and maps_legacy to lodash4
chore(NA): map src plugin data to lodash3
chore(NA): missing lodash.clonedeep dep
chore(NA): change packages kbn-config-schema deps
chore(NA): update renovate config
chore(NA): upgrade vis_type plugins to lodash4
chore(NA): move vis_type_vislib to lodash3
chore(NA): update visualizations and visualize to lodash4
chore(NA): remove lodash 3 types from src and move test to lodash4
chore(NA): move home, usage_collection and management to lodash 3
Revert "chore(NA): move home, usage_collection and management to lodash 3"
This reverts commit f86e8585f02d21550746569af54215b076a79a3d.
chore(NA): move kibana_legacy, saved_objects saved_objects_management into lodash3
chore(NA): update x-pack test to mock lodash4
Revert "chore(NA): move kibana_legacy, saved_objects saved_objects_management into lodash3"
This reverts commit 2d10fe450533e1b36db21d99cfae3ce996a244e0.
* chore(NA): move x-pack and packages to lodash 4
* chore(NA): remove mention to lodash from main package.json
* chore(NA): remove helper alias for lodash4 and make it the default lodash
* chore(NA): fix last failing types in the repo
* chore(NA): fix public api
* chore(NA): fix types for agg_row.tsx
* chore(NA): fix increment of optimizer modules in the rollup plugin
* chore(NA): migrate `src/core/public/http/fetch.ts` (#5)
* omit undefined query props
* just remove merge usage
* fix types
* chore(NA): fixes for feedback from apm team
* chore(NA): recover old behaviour on apm LoadingIndeicatorContext.tsx
* chore(NA): fixes for feedback from watson
* Platform lodash4 tweaks (#6)
* chore(NA): fix types and behaviour on src/core/server/elasticsearch/errors.ts
* Canvas fixes for lodash upgrade
* [APM] Adds unit test for APM service maps transform (#7)
* Adds a snapshot unit test for getConnections and rearranges some code to make testing easier
* reverts `ArrayList` back to `String[]` in the painless script within `fetch_service_paths_from_trace_ids.ts`
* chore(NA): update yarn.lock
* chore(NA): remove any and use a real type for alerts task runner
Co-authored-by: Gidi Meir Morris <github@gidi.io>
* chore(NA): used named import for triggers_actions_ui file
* chore(NA): fix eslint
* chore(NA): fix types
* Delete most uptime lodash references.
* Simplify. Clean up types.
* [Uptime] Delete most uptime lodash references (#8)
* Delete most uptime lodash references.
* Simplify. Clean up types.
* chore(NA): add eslint rule to avoid using lodash3
* chore(NA): apply changes on feedback from es-ui team
* fix some types (#9)
* Clean up some expressions types.
* chore(NA): missing ts-expect-error statements
* Upgrade lodash 4 vislib (#11)
* replace lodash 3 with lodash 4 on vislib plugin
* Further changes
* further replacement of lodash3 to 4
* further work on upgrading to lodash 4
* final changes to update lodash
* chore(NA): upgrade data plugin to lodash4
chore(NA): upgrade data plugin public to lodash4
chore(NA): fix typecheck task
chore(NA): fix agg_config with hasIn
chore(NA): assign to assignIn and has to hasIn
chore(NA): upgrade data plugin server to lodash4
chore(NA): new signature for core api
fix(NA): match behaviour between lodash3 and lodash4 for set in search_source
* chore(NA): remove lodash3 completely from the repo
* chore(NA): fix x-pack/test/api_integration/apis/metrics_ui/snapshot.ts missing content
* chore(NA): fix lodash usage on apm
* chore(NA): fix typecheck for maps
* Patch lodash template (#12)
* Applying changes from https://github.com/elastic/kibana/pull/64985
* Using isIterateeCall, because it seems less brittle
* Also patching `lodash/template` and `lodash/fp/template`
* Reorganizing some files...
* Revising comment
* Ends up `_` is a function also... I hate JavaScript
Co-authored-by: Pierre Gayvallet <pierre.gayvallet@gmail.com>
Co-authored-by: Josh Dover <me@joshdover.com>
Co-authored-by: Clint Andrew Hall <clint.hall@elastic.co>
Co-authored-by: Oliver Gupte <ogupte@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Gidi Meir Morris <github@gidi.io>
Co-authored-by: Justin Kambic <justin.kambic@elastic.co>
Co-authored-by: Stratoula Kalafateli <stratoula1@gmail.com>
Co-authored-by: Luke Elmers <luke.elmers@elastic.co>
Co-authored-by: Brandon Kobel <brandon.kobel@gmail.com>
Co-authored-by: kobelb <brandon.kobel@elastic.co>
2020-07-03 02:30:13 +02:00
|
|
|
const requiredPatterns = _.uniq(
|
2019-10-09 21:20:55 +02:00
|
|
|
state
|
|
|
|
? Object.values(state.layers)
|
2020-05-22 09:08:58 +02:00
|
|
|
.map((l) => l.indexPatternId)
|
2019-10-09 21:20:55 +02:00
|
|
|
.concat(state.currentIndexPatternId)
|
2020-06-26 16:33:09 +02:00
|
|
|
: [lastUsedIndexPatternId || defaultIndexPatternId || indexPatternRefs[0].id]
|
2019-10-09 21:20:55 +02:00
|
|
|
);
|
|
|
|
|
2020-10-06 10:15:41 +02:00
|
|
|
const currentIndexPatternId = initialContext?.indexPatternId ?? requiredPatterns[0];
|
2020-06-26 16:33:09 +02:00
|
|
|
setLastUsedIndexPatternId(storage, currentIndexPatternId);
|
|
|
|
|
2019-10-09 21:20:55 +02:00
|
|
|
const indexPatterns = await loadIndexPatterns({
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
cache: {},
|
2020-10-06 10:15:41 +02:00
|
|
|
patterns: initialContext ? [initialContext.indexPatternId] : requiredPatterns,
|
2019-10-09 21:20:55 +02:00
|
|
|
});
|
|
|
|
if (state) {
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
currentIndexPatternId,
|
|
|
|
indexPatternRefs,
|
|
|
|
indexPatterns,
|
2019-10-14 18:46:33 +02:00
|
|
|
existingFields: {},
|
2020-07-01 10:08:37 +02:00
|
|
|
isFirstExistenceFetch: true,
|
2019-10-09 21:20:55 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
currentIndexPatternId,
|
|
|
|
indexPatternRefs,
|
|
|
|
indexPatterns,
|
|
|
|
layers: {},
|
2019-10-14 18:46:33 +02:00
|
|
|
existingFields: {},
|
2020-07-01 10:08:37 +02:00
|
|
|
isFirstExistenceFetch: true,
|
2019-10-09 21:20:55 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function changeIndexPattern({
|
|
|
|
id,
|
|
|
|
state,
|
|
|
|
setState,
|
|
|
|
onError,
|
2020-06-26 16:33:09 +02:00
|
|
|
storage,
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
}: {
|
|
|
|
id: string;
|
|
|
|
state: IndexPatternPrivateState;
|
2019-10-14 18:46:33 +02:00
|
|
|
setState: SetState;
|
2019-10-09 21:20:55 +02:00
|
|
|
onError: ErrorHandler;
|
2020-06-26 16:33:09 +02:00
|
|
|
storage: IStorageWrapper;
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService: IndexPatternsService;
|
2019-10-09 21:20:55 +02:00
|
|
|
}) {
|
|
|
|
try {
|
|
|
|
const indexPatterns = await loadIndexPatterns({
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
cache: state.indexPatterns,
|
|
|
|
patterns: [id],
|
|
|
|
});
|
|
|
|
|
2020-05-22 09:08:58 +02:00
|
|
|
setState((s) => ({
|
2019-10-09 21:20:55 +02:00
|
|
|
...s,
|
|
|
|
layers: isSingleEmptyLayer(state.layers)
|
2020-05-22 09:08:58 +02:00
|
|
|
? _.mapValues(state.layers, (layer) => updateLayerIndexPattern(layer, indexPatterns[id]))
|
2019-10-09 21:20:55 +02:00
|
|
|
: state.layers,
|
|
|
|
indexPatterns: {
|
|
|
|
...s.indexPatterns,
|
|
|
|
[id]: indexPatterns[id],
|
|
|
|
},
|
|
|
|
currentIndexPatternId: id,
|
|
|
|
}));
|
2020-06-26 16:33:09 +02:00
|
|
|
setLastUsedIndexPatternId(storage, id);
|
2019-10-09 21:20:55 +02:00
|
|
|
} catch (err) {
|
|
|
|
onError(err);
|
|
|
|
}
|
|
|
|
}
|
2019-09-17 20:57:53 +02:00
|
|
|
|
2019-10-09 21:20:55 +02:00
|
|
|
export async function changeLayerIndexPattern({
|
|
|
|
indexPatternId,
|
|
|
|
layerId,
|
|
|
|
state,
|
|
|
|
setState,
|
|
|
|
onError,
|
2019-10-30 00:05:03 +01:00
|
|
|
replaceIfPossible,
|
2020-06-26 16:33:09 +02:00
|
|
|
storage,
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
}: {
|
|
|
|
indexPatternId: string;
|
|
|
|
layerId: string;
|
|
|
|
state: IndexPatternPrivateState;
|
2019-10-14 18:46:33 +02:00
|
|
|
setState: SetState;
|
2019-10-09 21:20:55 +02:00
|
|
|
onError: ErrorHandler;
|
2019-10-30 00:05:03 +01:00
|
|
|
replaceIfPossible?: boolean;
|
2020-06-26 16:33:09 +02:00
|
|
|
storage: IStorageWrapper;
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService: IndexPatternsService;
|
2019-10-09 21:20:55 +02:00
|
|
|
}) {
|
|
|
|
try {
|
|
|
|
const indexPatterns = await loadIndexPatterns({
|
2020-08-21 11:33:42 +02:00
|
|
|
indexPatternsService,
|
2019-10-09 21:20:55 +02:00
|
|
|
cache: state.indexPatterns,
|
|
|
|
patterns: [indexPatternId],
|
2019-09-17 20:57:53 +02:00
|
|
|
});
|
2019-10-09 21:20:55 +02:00
|
|
|
|
2020-05-22 09:08:58 +02:00
|
|
|
setState((s) => ({
|
2019-10-09 21:20:55 +02:00
|
|
|
...s,
|
|
|
|
layers: {
|
|
|
|
...s.layers,
|
|
|
|
[layerId]: updateLayerIndexPattern(s.layers[layerId], indexPatterns[indexPatternId]),
|
|
|
|
},
|
|
|
|
indexPatterns: {
|
|
|
|
...s.indexPatterns,
|
|
|
|
[indexPatternId]: indexPatterns[indexPatternId],
|
|
|
|
},
|
2019-10-30 00:05:03 +01:00
|
|
|
currentIndexPatternId: replaceIfPossible ? indexPatternId : s.currentIndexPatternId,
|
2019-10-09 21:20:55 +02:00
|
|
|
}));
|
2020-06-26 16:33:09 +02:00
|
|
|
setLastUsedIndexPatternId(storage, indexPatternId);
|
2019-10-09 21:20:55 +02:00
|
|
|
} catch (err) {
|
|
|
|
onError(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadIndexPatternRefs(
|
|
|
|
savedObjectsClient: SavedObjectsClient
|
|
|
|
): Promise<IndexPatternRef[]> {
|
|
|
|
const result = await savedObjectsClient.find<{ title: string }>({
|
|
|
|
type: 'index-pattern',
|
|
|
|
fields: ['title'],
|
|
|
|
perPage: 10000,
|
|
|
|
});
|
|
|
|
|
2019-10-30 00:05:03 +01:00
|
|
|
return result.savedObjects
|
2020-05-22 09:08:58 +02:00
|
|
|
.map((o) => ({
|
2019-10-30 00:05:03 +01:00
|
|
|
id: String(o.id),
|
|
|
|
title: (o.attributes as { title: string }).title,
|
|
|
|
}))
|
|
|
|
.sort((a, b) => {
|
|
|
|
return a.title.localeCompare(b.title);
|
|
|
|
});
|
2019-10-09 21:20:55 +02:00
|
|
|
}
|
|
|
|
|
2019-10-14 18:46:33 +02:00
|
|
|
export async function syncExistingFields({
|
|
|
|
indexPatterns,
|
|
|
|
dateRange,
|
|
|
|
fetchJson,
|
|
|
|
setState,
|
2020-07-01 10:08:37 +02:00
|
|
|
isFirstExistenceFetch,
|
|
|
|
currentIndexPatternTitle,
|
2020-03-12 09:03:40 +01:00
|
|
|
dslQuery,
|
2020-07-01 10:08:37 +02:00
|
|
|
showNoDataPopover,
|
2019-10-14 18:46:33 +02:00
|
|
|
}: {
|
|
|
|
dateRange: DateRange;
|
2020-07-16 09:54:46 +02:00
|
|
|
indexPatterns: Array<{
|
|
|
|
id: string;
|
|
|
|
title: string;
|
|
|
|
fields: IndexPatternField[];
|
|
|
|
timeFieldName?: string | null;
|
2020-08-26 09:09:40 +02:00
|
|
|
hasRestrictions: boolean;
|
2020-07-16 09:54:46 +02:00
|
|
|
}>;
|
2020-03-12 09:03:40 +01:00
|
|
|
fetchJson: HttpSetup['post'];
|
2019-10-14 18:46:33 +02:00
|
|
|
setState: SetState;
|
2020-07-01 10:08:37 +02:00
|
|
|
isFirstExistenceFetch: boolean;
|
|
|
|
currentIndexPatternTitle: string;
|
2020-03-12 09:03:40 +01:00
|
|
|
dslQuery: object;
|
2020-07-01 10:08:37 +02:00
|
|
|
showNoDataPopover: () => void;
|
2019-10-14 18:46:33 +02:00
|
|
|
}) {
|
2020-07-16 09:54:46 +02:00
|
|
|
const existenceRequests = indexPatterns.map((pattern) => {
|
2020-08-26 09:09:40 +02:00
|
|
|
if (pattern.hasRestrictions) {
|
|
|
|
return {
|
|
|
|
indexPatternTitle: pattern.title,
|
|
|
|
existingFieldNames: pattern.fields.map((field) => field.name),
|
|
|
|
};
|
|
|
|
}
|
2020-07-16 09:54:46 +02:00
|
|
|
const body: Record<string, string | object> = {
|
|
|
|
dslQuery,
|
|
|
|
fromDate: dateRange.fromDate,
|
|
|
|
toDate: dateRange.toDate,
|
|
|
|
};
|
2019-10-14 18:46:33 +02:00
|
|
|
|
2020-07-16 09:54:46 +02:00
|
|
|
if (pattern.timeFieldName) {
|
|
|
|
body.timeFieldName = pattern.timeFieldName;
|
|
|
|
}
|
2019-10-14 18:46:33 +02:00
|
|
|
|
2020-07-16 09:54:46 +02:00
|
|
|
return fetchJson(`${BASE_API_URL}/existing_fields/${pattern.id}`, {
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
}) as Promise<ExistingFields>;
|
|
|
|
});
|
2019-10-14 18:46:33 +02:00
|
|
|
|
2020-07-16 09:54:46 +02:00
|
|
|
try {
|
|
|
|
const emptinessInfo = await Promise.all(existenceRequests);
|
|
|
|
if (isFirstExistenceFetch) {
|
|
|
|
const fieldsCurrentIndexPattern = emptinessInfo.find(
|
|
|
|
(info) => info.indexPatternTitle === currentIndexPatternTitle
|
|
|
|
);
|
|
|
|
if (fieldsCurrentIndexPattern && fieldsCurrentIndexPattern.existingFieldNames.length === 0) {
|
|
|
|
showNoDataPopover();
|
|
|
|
}
|
2020-07-01 10:08:37 +02:00
|
|
|
}
|
|
|
|
|
2020-07-16 09:54:46 +02:00
|
|
|
setState((state) => ({
|
|
|
|
...state,
|
|
|
|
isFirstExistenceFetch: false,
|
|
|
|
existenceFetchFailed: false,
|
|
|
|
existingFields: emptinessInfo.reduce((acc, info) => {
|
|
|
|
acc[info.indexPatternTitle] = booleanMap(info.existingFieldNames);
|
|
|
|
return acc;
|
|
|
|
}, state.existingFields),
|
|
|
|
}));
|
|
|
|
} catch (e) {
|
|
|
|
// show all fields as available if fetch failed
|
|
|
|
setState((state) => ({
|
|
|
|
...state,
|
|
|
|
existenceFetchFailed: true,
|
|
|
|
existingFields: indexPatterns.reduce((acc, pattern) => {
|
|
|
|
acc[pattern.title] = booleanMap(pattern.fields.map((field) => field.name));
|
|
|
|
return acc;
|
|
|
|
}, state.existingFields),
|
|
|
|
}));
|
|
|
|
}
|
2019-10-14 18:46:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function booleanMap(keys: string[]) {
|
2019-11-13 17:00:02 +01:00
|
|
|
return keys.reduce((acc, key) => {
|
|
|
|
acc[key] = true;
|
|
|
|
return acc;
|
|
|
|
}, {} as Record<string, boolean>);
|
2019-10-14 18:46:33 +02:00
|
|
|
}
|
|
|
|
|
2019-10-09 21:20:55 +02:00
|
|
|
function isSingleEmptyLayer(layerMap: IndexPatternPrivateState['layers']) {
|
|
|
|
const layers = Object.values(layerMap);
|
|
|
|
return layers.length === 1 && layers[0].columnOrder.length === 0;
|
|
|
|
}
|