From bbfc5b4c4733f4d2a0a6e8bb768080e265191139 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 5 Dec 2022 13:24:12 +0200 Subject: [PATCH 01/40] [Visualize] Fixes the display of the modal viz creation wizard titles (#146978) ## Summary Fixes the way that the modal title is being displayed. It must have been broken with the new EUI upgrade. image Before the fix image --- .../agg_based_selection.tsx | 10 +++++---- .../group_selection/group_selection.tsx | 10 +++++---- .../search_selection/search_selection.tsx | 22 ++++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx index d4d2c1505bf8a..8ee63361321ef 100644 --- a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx +++ b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx @@ -57,10 +57,12 @@ class AggBasedSelection extends React.Component - +

+ +

diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx index 6bc982a824de1..908c1a621ebc8 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx @@ -67,10 +67,12 @@ function GroupSelection(props: GroupSelectionProps) { <> - +

+ +

diff --git a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx index 5771747794273..89814c0a474a1 100644 --- a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx +++ b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx @@ -33,16 +33,18 @@ export class SearchSelection extends React.Component { - {' '} - /{' '} - +

+ {' '} + /{' '} + +

From 23389a1b2a82586d76df47be0e4e011f997f0108 Mon Sep 17 00:00:00 2001 From: Kfir Peled <61654899+kfirpeled@users.noreply.github.com> Date: Mon, 5 Dec 2022 13:52:35 +0200 Subject: [PATCH 02/40] [Cloud Posture] Added CSPM integration support (#146842) ## Summary In this PR we have customized UI in the integration to support building agent policy the contains cspm config Screen Shot 2022-12-04 at 15 06 22 --- .../common/constants.ts | 16 +++++ .../public/common/constants.ts | 64 +++++++++++++++++-- .../get_enabled_csp_integration_details.ts | 10 ++- .../deployment_type_select.tsx | 21 +++--- .../policy_extension_create.tsx | 31 ++++++--- .../policy_extension_edit.tsx | 21 ++++-- .../components/fleet_extensions/utils.ts | 39 +++++++++-- 7 files changed, 168 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index a78266a51f279..539048af7bee1 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -46,3 +46,19 @@ export const CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE = 'csp-rule-template'; export const CLOUDBEAT_VANILLA = 'cloudbeat/cis_k8s'; // Integration input export const CLOUDBEAT_EKS = 'cloudbeat/cis_eks'; // Integration input +export const CLOUDBEAT_AWS = 'cloudbeat/cis_aws'; // Integration input +export const CLOUDBEAT_GCP = 'cloudbeat/cis_gcp'; // Integration input +export const CLOUDBEAT_AZURE = 'cloudbeat/cis_azure'; // Integration input +export const KSPM_POLICY_TEMPLATE = 'kspm'; +export const CSPM_POLICY_TEMPLATE = 'cspm'; +export const SUPPORTED_POLICY_TEMPLATES = [KSPM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE]; +export const SUPPORTED_CLOUDBEAT_INPUTS = [ + CLOUDBEAT_VANILLA, + CLOUDBEAT_EKS, + CLOUDBEAT_AWS, + CLOUDBEAT_GCP, + CLOUDBEAT_AZURE, +]; + +export type CLOUDBEAT_INTEGRATION = typeof SUPPORTED_CLOUDBEAT_INPUTS[number]; +export type POLICY_TEMPLATE = typeof SUPPORTED_POLICY_TEMPLATES[number]; diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 9c02bfe1ba4f6..0590b60d73f68 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -7,7 +7,15 @@ import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../common/constants'; +import { + CLOUDBEAT_EKS, + CLOUDBEAT_VANILLA, + CLOUDBEAT_AWS, + CLOUDBEAT_GCP, + CLOUDBEAT_AZURE, + CLOUDBEAT_INTEGRATION, + POLICY_TEMPLATE, +} from '../../common/constants'; export const statusColors = { passed: euiThemeVars.euiColorVis0, @@ -22,9 +30,57 @@ export const LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY = 'cloudPosture:findings:pageS export const LOCAL_STORAGE_PAGE_SIZE_BENCHMARK_KEY = 'cloudPosture:benchmark:pageSize'; export const LOCAL_STORAGE_PAGE_SIZE_RULES_KEY = 'cloudPosture:rules:pageSize'; -export type CloudPostureIntegrations = typeof cloudPostureIntegrations; +export type CloudPostureIntegrations = Record; +export interface CloudPostureIntegrationProps { + policyTemplate: POLICY_TEMPLATE; + name: string; + shortName: string; + options: Array<{ + type: CLOUDBEAT_INTEGRATION; + name: string; + benchmark: string; + }>; +} -export const cloudPostureIntegrations = { +export const cloudPostureIntegrations: CloudPostureIntegrations = { + cspm: { + policyTemplate: 'cspm', + name: i18n.translate('xpack.csp.cspmIntegration.integration.nameTitle', { + defaultMessage: 'Cloud Security Posture Management', + }), + shortName: i18n.translate('xpack.csp.cspmIntegration.integration.shortNameTitle', { + defaultMessage: 'CSPM', + }), + options: [ + { + type: CLOUDBEAT_AWS, + name: i18n.translate('xpack.csp.cspmIntegration.awsOption.nameTitle', { + defaultMessage: 'Amazon Web Services', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.awsOption.benchmarkTitle', { + defaultMessage: 'CIS AWS', + }), + }, + { + type: CLOUDBEAT_GCP, + name: i18n.translate('xpack.csp.cspmIntegration.gcpOption.nameTitle', { + defaultMessage: 'GCP', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.gcpOption.benchmarkTitle', { + defaultMessage: 'CIS GCP', + }), + }, + { + type: CLOUDBEAT_AZURE, + name: i18n.translate('xpack.csp.cspmIntegration.azureOption.nameTitle', { + defaultMessage: 'Azure', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.azureOption.benchmarkTitle', { + defaultMessage: 'CIS Azure', + }), + }, + ], + }, kspm: { policyTemplate: 'kspm', name: i18n.translate('xpack.csp.kspmIntegration.integration.nameTitle', { @@ -54,4 +110,4 @@ export const cloudPostureIntegrations = { }, ], }, -} as const; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts index 6cc02ac9aedc1..2fed31c2f8cc4 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts @@ -6,6 +6,7 @@ */ import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { SUPPORTED_CLOUDBEAT_INPUTS } from '../../../common/constants'; import { cloudPostureIntegrations, CloudPostureIntegrations } from '../constants'; const isPolicyTemplate = (name: unknown): name is keyof CloudPostureIntegrations => @@ -13,7 +14,14 @@ const isPolicyTemplate = (name: unknown): name is keyof CloudPostureIntegrations export const getEnabledCspIntegrationDetails = (packageInfo?: PackagePolicy) => { const enabledInput = packageInfo?.inputs.find((input) => input.enabled); - if (!enabledInput || !isPolicyTemplate(enabledInput.policy_template)) return null; + + // Check for valid and support input + if ( + !enabledInput || + !isPolicyTemplate(enabledInput.policy_template) || + !SUPPORTED_CLOUDBEAT_INPUTS.includes(enabledInput.type) + ) + return null; const integration = cloudPostureIntegrations[enabledInput.policy_template]; const enabledIntegrationOption = integration.options.find( diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx index b01b5073a0e1b..bc5c61fa0370b 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx @@ -17,18 +17,19 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { cloudPostureIntegrations } from '../../common/constants'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants'; - -export type InputType = typeof CLOUDBEAT_EKS | typeof CLOUDBEAT_VANILLA; +import { CLOUDBEAT_INTEGRATION, POLICY_TEMPLATE } from '../../../common/constants'; interface Props { - type: InputType; - onChange?: (type: InputType) => void; + policyTemplate: POLICY_TEMPLATE; + type: CLOUDBEAT_INTEGRATION; + onChange?: (type: CLOUDBEAT_INTEGRATION) => void; isDisabled?: boolean; } -const kubeDeployOptions: Array> = - cloudPostureIntegrations.kspm.options.map((o) => ({ value: o.type, label: o.name })); +const kubeDeployOptions = ( + policyTemplate: POLICY_TEMPLATE +): Array> => + cloudPostureIntegrations[policyTemplate].options.map((o) => ({ value: o.type, label: o.name })); const KubernetesDeploymentFieldLabel = () => ( ( ); -export const DeploymentTypeSelect = ({ type, isDisabled, onChange }: Props) => ( +export const DeploymentTypeSelect = ({ policyTemplate, type, isDisabled, onChange }: Props) => ( }> }> o.value === type)} + options={kubeDeployOptions(policyTemplate)} + selectedOptions={kubeDeployOptions(policyTemplate).filter((o) => o.value === type)} isDisabled={isDisabled} onChange={(options) => !isDisabled && onChange?.(options[0].value!)} /> diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx index ae5d79984da7e..790cd8978725c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx @@ -7,16 +7,22 @@ import React, { memo } from 'react'; import { EuiForm } from '@elastic/eui'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import { CLOUDBEAT_EKS } from '../../../common/constants'; -import { DeploymentTypeSelect, InputType } from './deployment_type_select'; +import { CLOUDBEAT_AWS, CLOUDBEAT_EKS, CLOUDBEAT_INTEGRATION } from '../../../common/constants'; +import { DeploymentTypeSelect } from './deployment_type_select'; import { EksFormWrapper } from './eks_form'; -import { getEnabledInputType, getUpdatedDeploymentType, getUpdatedEksVar } from './utils'; +import { + getEnabledInput, + getEnabledInputType, + getUpdatedDeploymentType, + getUpdatedEksVar, +} from './utils'; export const CspCreatePolicyExtension = memo( ({ newPolicy, onChange }) => { const selectedDeploymentType = getEnabledInputType(newPolicy.inputs); - - const updateDeploymentType = (inputType: InputType) => + const selectedInput = getEnabledInput(newPolicy.inputs); + const policyTemplate = selectedInput?.policy_template; + const updateDeploymentType = (inputType: CLOUDBEAT_INTEGRATION) => onChange(getUpdatedDeploymentType(newPolicy, inputType)); const updateEksVar = (key: string, value: string) => @@ -24,9 +30,18 @@ export const CspCreatePolicyExtension = memo - - {selectedDeploymentType === CLOUDBEAT_EKS && ( - + {selectedInput && (policyTemplate === 'kspm' || policyTemplate === 'cspm') && ( + <> + + {(selectedDeploymentType === CLOUDBEAT_EKS || + selectedDeploymentType === CLOUDBEAT_AWS) && ( + + )} + )} ); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx index 33ed6dced08ad..e268dac8cd14e 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx @@ -7,23 +7,34 @@ import React, { memo } from 'react'; import { EuiForm } from '@elastic/eui'; import type { PackagePolicyEditExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import { CLOUDBEAT_EKS } from '../../../common/constants'; +import { CLOUDBEAT_EKS, CLOUDBEAT_AWS } from '../../../common/constants'; import { DeploymentTypeSelect } from './deployment_type_select'; import { EksFormWrapper } from './eks_form'; -import { getEnabledInputType, getUpdatedEksVar } from './utils'; +import { getEnabledInput, getEnabledInputType, getUpdatedEksVar } from './utils'; export const CspEditPolicyExtension = memo( ({ newPolicy, onChange }) => { const selectedDeploymentType = getEnabledInputType(newPolicy.inputs); + const selectedInput = getEnabledInput(newPolicy.inputs); + const policyTemplate = selectedInput?.policy_template; const updateEksVar = (key: string, value: string) => onChange(getUpdatedEksVar(newPolicy, key, value)); return ( - - {selectedDeploymentType === CLOUDBEAT_EKS && ( - + {(policyTemplate === 'kspm' || policyTemplate === 'cspm') && ( + <> + + {(selectedDeploymentType === CLOUDBEAT_EKS || + selectedDeploymentType === CLOUDBEAT_AWS) && ( + + )} + )} ); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index 9641606abfcf7..2f2285ad5c4ce 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -5,15 +5,42 @@ * 2.0. */ import type { NewPackagePolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants'; -import type { InputType } from './deployment_type_select'; +import { + CLOUDBEAT_AWS, + CLOUDBEAT_EKS, + CLOUDBEAT_VANILLA, + CLOUDBEAT_INTEGRATION, + SUPPORTED_POLICY_TEMPLATES, + POLICY_TEMPLATE, +} from '../../../common/constants'; export const isEksInput = (input: NewPackagePolicyInput) => input.type === CLOUDBEAT_EKS; +export const inputsWithVars = [CLOUDBEAT_EKS, CLOUDBEAT_AWS]; +const defaultInputType: Record = { + kspm: CLOUDBEAT_VANILLA, + cspm: CLOUDBEAT_AWS, +}; +export const getEnabledInputType = (inputs: NewPackagePolicy['inputs']): CLOUDBEAT_INTEGRATION => { + const enabledInput = getEnabledInput(inputs); + + if (enabledInput) return enabledInput.type as CLOUDBEAT_INTEGRATION; + + const policyTemplate = inputs[0].policy_template as POLICY_TEMPLATE | undefined; + + if (policyTemplate && SUPPORTED_POLICY_TEMPLATES.includes(policyTemplate)) + return defaultInputType[policyTemplate]; + + throw new Error('unsupported policy template'); +}; -export const getEnabledInputType = (inputs: NewPackagePolicy['inputs']): InputType => - (inputs.find((input) => input.enabled)?.type as InputType) || CLOUDBEAT_VANILLA; +export const getEnabledInput = ( + inputs: NewPackagePolicy['inputs'] +): NewPackagePolicyInput | undefined => inputs.find((input) => input.enabled); -export const getUpdatedDeploymentType = (newPolicy: NewPackagePolicy, inputType: InputType) => ({ +export const getUpdatedDeploymentType = ( + newPolicy: NewPackagePolicy, + inputType: CLOUDBEAT_INTEGRATION +) => ({ isValid: true, // TODO: add validations updatedPolicy: { ...newPolicy, @@ -33,7 +60,7 @@ export const getUpdatedEksVar = (newPolicy: NewPackagePolicy, key: string, value updatedPolicy: { ...newPolicy, inputs: newPolicy.inputs.map((item) => - isEksInput(item) ? getUpdatedStreamVars(item, key, value) : item + inputsWithVars.includes(item.type) ? getUpdatedStreamVars(item, key, value) : item ), }, }); From f72e50fdd6e85f5ad0c27f1777b88522dd2b7ac1 Mon Sep 17 00:00:00 2001 From: Kfir Peled <61654899+kfirpeled@users.noreply.github.com> Date: Mon, 5 Dec 2022 13:52:52 +0200 Subject: [PATCH 03/40] [Cloud Posture] Remove k8s instructions for cspm policies (#146843) ## Summary When installing CSPM the kubernetes deployment is not relevant and shouldn't be visible. This PR is fixing that Screen Shot 2022-12-04 at 15 41 00 ## How to test it In order to install CSPM integration you use cloud_security_posture 1.1.0 which is recently available https://github.com/elastic/integrations/pull/4752 --- x-pack/plugins/fleet/common/constants/epm.ts | 1 + x-pack/plugins/fleet/common/index.ts | 1 + .../agent_enrollment_flyout/hooks.tsx | 20 ++++++++++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index 08efe1f717b44..c95754bc265d7 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -17,6 +17,7 @@ export const FLEET_APM_PACKAGE = 'apm'; export const FLEET_SYNTHETICS_PACKAGE = 'synthetics'; export const FLEET_KUBERNETES_PACKAGE = 'kubernetes'; export const FLEET_CLOUD_SECURITY_POSTURE_PACKAGE = 'cloud_security_posture'; +export const FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE = 'kspm'; export const PACKAGE_TEMPLATE_SUFFIX = '@package'; export const USER_SETTINGS_TEMPLATE_SUFFIX = '@custom'; diff --git a/x-pack/plugins/fleet/common/index.ts b/x-pack/plugins/fleet/common/index.ts index 626a40885b502..5b3765bf9e40b 100644 --- a/x-pack/plugins/fleet/common/index.ts +++ b/x-pack/plugins/fleet/common/index.ts @@ -17,6 +17,7 @@ export { FLEET_ELASTIC_AGENT_PACKAGE, FLEET_KUBERNETES_PACKAGE, FLEET_CLOUD_SECURITY_POSTURE_PACKAGE, + FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE, FLEET_ENDPOINT_PACKAGE, // Saved object type AGENT_POLICY_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx index 886ce736b3625..46341042102f0 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx @@ -9,12 +9,16 @@ import { i18n } from '@kbn/i18n'; import type { PackagePolicy, AgentPolicy } from '../../types'; import { sendGetOneAgentPolicy, useStartServices } from '../../hooks'; -import { FLEET_KUBERNETES_PACKAGE, FLEET_CLOUD_SECURITY_POSTURE_PACKAGE } from '../../../common'; +import { + FLEET_KUBERNETES_PACKAGE, + FLEET_CLOUD_SECURITY_POSTURE_PACKAGE, + FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE, +} from '../../../common'; import type { K8sMode } from './types'; // Packages that requires custom elastic-agent manifest -const K8S_PACKAGES = new Set([FLEET_KUBERNETES_PACKAGE, FLEET_CLOUD_SECURITY_POSTURE_PACKAGE]); +const K8S_PACKAGES = new Set([FLEET_KUBERNETES_PACKAGE]); export function useAgentPolicyWithPackagePolicies(policyId?: string) { const [agentPolicyWithPackagePolicies, setAgentPolicy] = useState(null); @@ -66,4 +70,14 @@ export function useIsK8sPolicy(agentPolicy?: AgentPolicy) { return { isK8s }; } -const isK8sPackage = (pkg: PackagePolicy) => K8S_PACKAGES.has(pkg.package?.name as string); +const isK8sPackage = (pkg: PackagePolicy) => { + const name = pkg.package?.name as string; + if (name === FLEET_CLOUD_SECURITY_POSTURE_PACKAGE) { + return pkg.inputs.some( + (input) => + input.enabled && input.policy_template === FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE + ); + } + + return K8S_PACKAGES.has(name); +}; From 4735ad81cf000e6f5124fdfc73a502054e127311 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 5 Dec 2022 16:06:54 +0300 Subject: [PATCH 04/40] Update code owner for `kbn-monaco` package (#146967) ## Summary Replace @elastic/kibana-app-services -> @elastic/kibana-global-experience for `kbn-monaco` package While working on #146379 I just saw that the plugin has the wrong code-owner. Let's fix it Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 2 +- packages/kbn-monaco/kibana.jsonc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4b598ff43309d..1de1a29e9326a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -953,7 +953,7 @@ packages/kbn-logging-mocks @elastic/kibana-core packages/kbn-managed-vscode-config @elastic/kibana-operations packages/kbn-managed-vscode-config-cli @elastic/kibana-operations packages/kbn-mapbox-gl @elastic/kibana-gis -packages/kbn-monaco @elastic/kibana-app-services +packages/kbn-monaco @elastic/kibana-global-experience packages/kbn-optimizer @elastic/kibana-operations packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations packages/kbn-osquery-io-ts-types @elastic/security-asset-management diff --git a/packages/kbn-monaco/kibana.jsonc b/packages/kbn-monaco/kibana.jsonc index 42524f21bd542..0634c00ae6f77 100644 --- a/packages/kbn-monaco/kibana.jsonc +++ b/packages/kbn-monaco/kibana.jsonc @@ -1,7 +1,7 @@ { "type": "shared-common", "id": "@kbn/monaco", - "owner": "@elastic/kibana-app-services", + "owner": "@elastic/kibana-global-experience", "runtimeDeps": [], "typeDeps": [] } From ed9e9627706d9b894f429a5b8084f5afa9f5f271 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Mon, 5 Dec 2022 08:16:15 -0500 Subject: [PATCH 05/40] [Security Solution] [Exceptions] Hook for exceptions to fetch the security solution default data view was missing the space id (#146915) ## Summary append space id to security solution default data view in `useFetchIndexPatterns` hook in rule exceptions Co-authored-by: Gloria Hornero --- .../logic/use_exception_flyout_data.tsx | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_exception_flyout_data.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_exception_flyout_data.tsx index cec9be976592e..7fcd1fae95c83 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_exception_flyout_data.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_exception_flyout_data.tsx @@ -24,19 +24,32 @@ export interface ReturnUseFetchExceptionFlyoutData { * */ export const useFetchIndexPatterns = (rules: Rule[] | null): ReturnUseFetchExceptionFlyoutData => { - const { data } = useKibana().services; + const { data, spaces } = useKibana().services; const [dataViewLoading, setDataViewLoading] = useState(false); + const [activeSpaceId, setActiveSpaceId] = useState(''); const isSingleRule = useMemo(() => rules != null && rules.length === 1, [rules]); const isMLRule = useMemo( () => rules != null && isSingleRule && rules[0].type === 'machine_learning', [isSingleRule, rules] ); + + useEffect(() => { + const fetchAndSetActiveSpace = async () => { + if (spaces) { + const aSpace = await spaces.getActiveSpace(); + setActiveSpaceId(aSpace.id); + } + }; + fetchAndSetActiveSpace(); + }, [spaces]); // If data view is defined, it superceeds use of rule defined index patterns. // If no rule is available, use fields from default data view id. const memoDataViewId = useMemo( () => - rules != null && isSingleRule ? rules[0].data_view_id || null : 'security-solution-default', - [isSingleRule, rules] + rules != null && isSingleRule + ? rules[0].data_view_id || null + : `security-solution-${activeSpaceId}`, + [isSingleRule, rules, activeSpaceId] ); const memoNonDataViewIndexPatterns = useMemo( @@ -74,7 +87,10 @@ export const useFetchIndexPatterns = (rules: Rule[] | null): ReturnUseFetchExcep const [dataViewIndexPatterns, setDataViewIndexPatterns] = useState(null); useEffect(() => { const fetchSingleDataView = async () => { - if (memoDataViewId) { + // ensure the memoized data view includes a space id, otherwise + // we could be trying to fetch a data view that does not exist, which would + // throw an error here. + if (activeSpaceId !== '' && memoDataViewId) { setDataViewLoading(true); const dv = await data.dataViews.get(memoDataViewId); setDataViewLoading(false); @@ -83,7 +99,7 @@ export const useFetchIndexPatterns = (rules: Rule[] | null): ReturnUseFetchExcep }; fetchSingleDataView(); - }, [memoDataViewId, data.dataViews, setDataViewIndexPatterns]); + }, [memoDataViewId, data.dataViews, setDataViewIndexPatterns, activeSpaceId]); // Determine whether to use index patterns or data views const indexPatternsToUse = useMemo( From 131aa1b3c8fa0fc9dd8e1b31cb57dada65e7311b Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 5 Dec 2022 15:25:59 +0200 Subject: [PATCH 06/40] [Visualize2Lens] heatmap with dynamic bands is not converted correctly (#146970) ## Summary Fixes: #146961 For dynamic calculated ranges in heatmap we should use percent palette. --- .../configurations/index.test.ts | 2 +- .../convert_to_lens/configurations/palette.ts | 5 ++- .../lens/open_in_lens/agg_based/heatmap.ts | 38 +++++++++---------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts index 3f60b6fde0a94..523ed9ddba21c 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts @@ -90,7 +90,7 @@ describe('getConfiguration', () => { progression: 'fixed', rangeMax: 100, rangeMin: 0, - rangeType: 'number', + rangeType: 'percent', reverse: false, stops: [ { color: '#F7FBFF', stop: 12.5 }, diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts index 32187e184d4ef..c92b3780796e9 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts @@ -37,13 +37,14 @@ export const getPaletteForHeatmap = async (params: HeatmapVisParams) => { true ); const colorsRange: Range[] = [{ from: stop[0], to: stop[stop.length - 1], type: 'range' }]; - const { colorSchema, invertColors, percentageMode } = params; + const { colorSchema, invertColors } = params; + // palette is type of percent, if user wants dynamic calulated ranges const percentageModeConfig = getPercentageModeConfig( { colorsRange, colorSchema, invertColors, - percentageMode, + percentageMode: true, }, false ); diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index 8556ae601daf9..4f43bf466f892 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -67,19 +67,19 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(debugState.legend!.items).to.eql([ { color: '#006837', - key: '0 - 25', - name: '0 - 25', + key: '1,322 - 1,717.5', + name: '1,322 - 1,717.5', }, - { color: '#86CB66', key: '25 - 50', name: '25 - 50' }, + { color: '#86CB66', key: '1,717.5 - 2,113', name: '1,717.5 - 2,113' }, { color: '#FEFEBD', - key: '50 - 75', - name: '50 - 75', + key: '2,113 - 2,508.5', + name: '2,113 - 2,508.5', }, { color: '#F88D52', - key: '75 - 100', - name: '75 - 100', + key: '2,508.5 - 2,904', + name: '2,508.5 - 2,904', }, ]); }); @@ -125,33 +125,33 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(debugState.legend!.items).to.eql([ { color: '#006837', - key: '0 - 16.67', - name: '0 - 16.67', + key: '1,322 - 1,585.67', + name: '1,322 - 1,585.67', }, { color: '#4CB15D', - key: '16.67 - 33.33', - name: '16.67 - 33.33', + key: '1,585.67 - 1,849.33', + name: '1,585.67 - 1,849.33', }, { color: '#B7E075', - key: '33.33 - 50', - name: '33.33 - 50', + key: '1,849.33 - 2,113', + name: '1,849.33 - 2,113', }, { color: '#FEFEBD', - key: '50 - 66.67', - name: '50 - 66.67', + key: '2,113 - 2,376.67', + name: '2,113 - 2,376.67', }, { color: '#FDBF6F', - key: '66.67 - 83.33', - name: '66.67 - 83.33', + key: '2,376.67 - 2,640.33', + name: '2,376.67 - 2,640.33', }, { color: '#EA5839', - key: '83.33 - 100', - name: '83.33 - 100', + key: '2,640.33 - 2,904', + name: '2,640.33 - 2,904', }, ]); }); From 917d9187fa32fbb9bed5aa70e7402db960ff03f5 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Mon, 5 Dec 2022 14:29:30 +0100 Subject: [PATCH 07/40] [ML] Enable Change Point Detection UI (#146991) ## Summary Enables [Change Point Detection UI ](https://github.com/elastic/kibana/pull/144093) --- x-pack/plugins/aiops/common/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/aiops/common/index.ts b/x-pack/plugins/aiops/common/index.ts index 0726447532aa2..b4ec6c287b22d 100755 --- a/x-pack/plugins/aiops/common/index.ts +++ b/x-pack/plugins/aiops/common/index.ts @@ -21,4 +21,4 @@ export const PLUGIN_NAME = 'AIOps'; */ export const AIOPS_ENABLED = true; -export const CHANGE_POINT_DETECTION_ENABLED = false; +export const CHANGE_POINT_DETECTION_ENABLED = true; From d1de864dc551c2ff65fb0aec598ab0149232039d Mon Sep 17 00:00:00 2001 From: Davis McPhee Date: Mon, 5 Dec 2022 09:42:47 -0400 Subject: [PATCH 08/40] [Discover] Update Unified Histogram to use Lens (#143117) ## Summary This PR updates Discover and Unified Histogram to use Lens for the histogram chart, and removes Discover as a Lens dependency: ![discover_lens](https://user-images.githubusercontent.com/25592674/202795541-a7dc33d6-5529-4097-9de4-f2155fd81052.gif) Note that there are some additional changes to make in followup PRs before this will be ready for solutions adoption: - Add the ability for Unified Histogram to support manually refetching in addition to auto refetching. - Currently Unified Histogram watches for changes to the query, filters, and time range. We will need to update this so those dependencies are passed as props instead. - It would be helpful to add some usage documentation to Unified Histogram to help other teams implement it in their projects. A la carte deployment: https://davismcphee-pr-143117-enhancement-unified-histogram-lens.kbndev.co. Flaky test run: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1571. Resolves #143108. Resolves #142390. ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] ~[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] ~Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~ - [ ] ~If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) Co-authored-by: Dzmitry Tamashevich Co-authored-by: Matthias Wilhelm Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../migrations/check_registered_types.test.ts | 2 +- src/plugins/dashboard/tsconfig.json | 1 - src/plugins/discover/kibana.json | 3 +- .../__mocks__/data_view_with_timefield.ts | 5 + .../public/__mocks__/search_session.ts | 9 +- .../discover/public/__mocks__/services.ts | 1 + .../layout/__stories__/get_layout_props.ts | 12 - .../layout/discover_histogram_layout.test.tsx | 220 ++++++++ .../layout/discover_histogram_layout.tsx | 87 ++++ .../components/layout/discover_layout.scss | 6 +- .../layout/discover_layout.test.tsx | 88 +--- .../components/layout/discover_layout.tsx | 108 ++-- .../layout/discover_main_content.test.tsx | 189 ++----- .../layout/discover_main_content.tsx | 168 ++---- .../layout/reset_search_button.test.tsx | 20 + .../components/layout/reset_search_button.tsx | 35 ++ .../main/components/layout/types.ts | 6 +- .../layout/use_discover_histogram.test.ts | 453 +++++++++++------ .../layout/use_discover_histogram.ts | 232 ++++++--- .../loading_spinner/loading_spinner.scss | 4 - .../loading_spinner/loading_spinner.tsx | 25 +- .../application/main/discover_main_app.tsx | 2 + .../main/hooks/use_discover_state.ts | 17 +- .../main/hooks/use_inspector.test.ts | 19 +- .../application/main/hooks/use_inspector.ts | 29 +- .../main/hooks/use_saved_search.test.ts | 1 - .../main/hooks/use_saved_search.ts | 11 +- .../hooks/use_saved_search_messages.test.ts | 40 +- .../main/hooks/use_saved_search_messages.ts | 64 ++- .../main/services/discover_search_session.ts | 3 + .../main/services/discover_state.ts | 5 + .../utils/aggregate_request_adapter.test.ts | 42 ++ .../main/utils/aggregate_request_adapter.ts | 132 +++++ .../application/main/utils/fetch_all.test.ts | 104 ++-- .../application/main/utils/fetch_all.ts | 123 ++--- .../main/utils/fetch_chart.test.ts | 138 ----- .../application/main/utils/fetch_chart.ts | 75 --- .../main/utils/fetch_documents.test.ts | 20 +- .../main/utils/fetch_total_hits.test.ts | 57 --- .../main/utils/fetch_total_hits.ts | 58 --- .../main/utils/get_state_defaults.test.ts | 2 + .../main/utils/get_state_defaults.ts | 5 + .../main/utils/persist_saved_search.ts | 6 + src/plugins/discover/public/build_services.ts | 3 + src/plugins/discover/public/locator.ts | 7 + src/plugins/discover/public/plugin.tsx | 2 + .../saved_searches/get_saved_searches.test.ts | 2 + .../saved_searches_utils.test.ts | 2 + .../saved_searches/saved_searches_utils.ts | 2 + .../public/services/saved_searches/types.ts | 2 + .../server/saved_objects/search.ts | 1 + src/plugins/unified_histogram/kibana.json | 2 +- .../__mocks__/data_view_with_timefield.ts | 6 + .../public/__mocks__/services.ts | 1 + .../chart/breakdown_field_selector.test.tsx | 73 +++ .../public/chart/breakdown_field_selector.tsx | 89 ++++ ....test.ts => build_bucket_interval.test.ts} | 43 +- ...chart_data.ts => build_bucket_interval.ts} | 24 +- .../chart/build_point_series_data.test.ts | 120 ----- .../public/chart/build_point_series_data.ts | 45 -- .../public/chart/chart.test.tsx | 95 ++-- .../unified_histogram/public/chart/chart.tsx | 236 ++++++--- .../public/chart/consts.ts} | 8 +- .../chart/field_supports_breakdown.test.ts | 35 ++ .../public/chart/field_supports_breakdown.ts | 14 + .../public/chart/get_chart_agg_config.test.ts | 14 +- .../public/chart/get_chart_agg_configs.ts | 5 +- .../public/chart/get_dimensions.test.ts | 58 --- .../public/chart/get_dimensions.ts | 56 -- .../public/chart/get_lens_attributes.test.ts | 480 ++++++++++++++++++ .../public/chart/get_lens_attributes.ts | 180 +++++++ .../public/chart/histogram.test.tsx | 282 +++++++--- .../public/chart/histogram.tsx | 462 ++++++----------- .../unified_histogram/public/chart/index.ts | 2 - .../public/chart/use_chart_actions.test.ts | 82 +++ .../public/chart/use_chart_actions.ts | 53 ++ .../public/chart/use_chart_panels.test.ts | 4 - .../public/chart/use_chart_panels.ts | 4 +- .../public/chart/use_chart_styles.tsx | 75 +++ .../public/chart/use_refetch_id.test.ts | 68 +++ .../public/chart/use_refetch_id.ts | 121 +++++ .../public/chart/use_request_params.tsx | 58 +++ .../public/chart/use_time_range.test.tsx | 239 +++++++++ .../public/chart/use_time_range.tsx | 127 +++++ .../public/chart/use_total_hits.test.ts | 212 ++++++++ .../public/chart/use_total_hits.ts | 177 +++++++ .../public/hits_counter/hits_counter.test.tsx | 16 +- .../public/hits_counter/hits_counter.tsx | 7 +- src/plugins/unified_histogram/public/index.ts | 9 +- .../public/layout/layout.test.tsx | 26 +- .../public/layout/layout.tsx | 60 ++- src/plugins/unified_histogram/public/types.ts | 137 ++--- src/plugins/unified_histogram/tsconfig.json | 5 +- .../apps/discover/group1/_discover.ts | 63 --- .../discover/group1/_discover_histogram.ts | 103 +++- .../group1/_discover_histogram_breakdown.ts | 61 +++ .../apps/discover/group1/_inspector.ts | 10 +- test/functional/apps/discover/group1/index.ts | 1 + .../apps/discover/group2/_huge_fields.ts | 1 + .../discover/group2/_search_on_page_load.ts | 2 +- test/functional/page_objects/discover_page.ts | 18 + test/functional/page_objects/time_picker.ts | 9 +- x-pack/plugins/data_visualizer/tsconfig.json | 3 +- x-pack/plugins/lens/kibana.json | 3 +- .../lens/public/app_plugin/lens_top_nav.tsx | 14 +- .../lens/public/app_plugin/mounter.tsx | 4 +- .../plugins/lens/public/app_plugin/types.ts | 4 +- .../form_based/field_item.test.tsx | 13 +- .../datasources/form_based/field_item.tsx | 5 +- .../datasources/form_based/form_based.tsx | 10 +- .../public/datasources/form_based/index.ts | 8 +- .../public/embeddable/embeddable.test.tsx | 30 +- .../lens/public/embeddable/embeddable.tsx | 15 +- x-pack/plugins/lens/public/plugin.ts | 46 +- .../open_in_discover_action.test.ts | 24 +- .../open_in_discover_action.ts | 10 +- .../open_in_discover_drilldown.test.tsx | 5 +- .../open_in_discover_drilldown.tsx | 12 +- .../open_in_discover_helpers.ts | 39 +- x-pack/plugins/observability/tsconfig.json | 1 + .../translations/translations/fr-FR.json | 5 - .../translations/translations/ja-JP.json | 5 - .../translations/translations/zh-CN.json | 5 - .../apps/discover/visualize_field.ts | 22 + .../apps/lens/group2/show_underlying_data.ts | 1 - .../apps/transform/creation_index_pattern.ts | 4 +- 126 files changed, 4690 insertions(+), 2324 deletions(-) create mode 100644 src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx create mode 100644 src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx create mode 100644 src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx create mode 100644 src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx delete mode 100644 src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss create mode 100644 src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts create mode 100644 src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts delete mode 100644 src/plugins/discover/public/application/main/utils/fetch_chart.test.ts delete mode 100644 src/plugins/discover/public/application/main/utils/fetch_chart.ts delete mode 100644 src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts delete mode 100644 src/plugins/discover/public/application/main/utils/fetch_total_hits.ts create mode 100644 src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx create mode 100644 src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx rename src/plugins/unified_histogram/public/chart/{build_chart_data.test.ts => build_bucket_interval.test.ts} (69%) rename src/plugins/unified_histogram/public/chart/{build_chart_data.ts => build_bucket_interval.ts} (68%) delete mode 100644 src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts delete mode 100644 src/plugins/unified_histogram/public/chart/build_point_series_data.ts rename src/plugins/{discover/public/application/main/components/loading_spinner/discover_field_visualize.stories.tsx => unified_histogram/public/chart/consts.ts} (59%) create mode 100644 src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts create mode 100644 src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts delete mode 100644 src/plugins/unified_histogram/public/chart/get_dimensions.test.ts delete mode 100644 src/plugins/unified_histogram/public/chart/get_dimensions.ts create mode 100644 src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts create mode 100644 src/plugins/unified_histogram/public/chart/get_lens_attributes.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_chart_actions.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_chart_styles.tsx create mode 100644 src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_refetch_id.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_request_params.tsx create mode 100644 src/plugins/unified_histogram/public/chart/use_time_range.test.tsx create mode 100644 src/plugins/unified_histogram/public/chart/use_time_range.tsx create mode 100644 src/plugins/unified_histogram/public/chart/use_total_hits.test.ts create mode 100644 src/plugins/unified_histogram/public/chart/use_total_hits.ts create mode 100644 test/functional/apps/discover/group1/_discover_histogram_breakdown.ts diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index 983adcac14c91..ff50b46b9b3f3 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -124,7 +124,7 @@ describe('checking migration metadata changes on all registered SO types', () => "osquery-saved-query": "7b213b4b7a3e59350e99c50e8df9948662ed493a", "query": "4640ef356321500a678869f24117b7091a911cb6", "sample-data-telemetry": "8b10336d9efae6f3d5593c4cc89fb4abcdf84e04", - "search": "d26771bcf7cd271162aab3a610b75249631ef6b1", + "search": "c48f5ab5d94545780ea98de1bff9e39f17f3606b", "search-session": "ba383309da68a15be3765977f7a44c84f0ec7964", "search-telemetry": "beb3fc25488c753f2a6dcff1845d667558712b66", "security-rule": "e0dfdba5d66139d0300723b2e6672993cd4a11f3", diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index 96a2757909c12..390fc6f6a0a5e 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -26,7 +26,6 @@ { "path": "../screenshot_mode/tsconfig.json" }, { "path": "../ui_actions/tsconfig.json" }, { "path": "../charts/tsconfig.json" }, - { "path": "../discover/tsconfig.json" }, { "path": "../visualizations/tsconfig.json" }, { "path": "../../../x-pack/plugins/spaces/tsconfig.json" } ] diff --git a/src/plugins/discover/kibana.json b/src/plugins/discover/kibana.json index e9d78d844a6e0..238de02475307 100644 --- a/src/plugins/discover/kibana.json +++ b/src/plugins/discover/kibana.json @@ -29,7 +29,8 @@ "usageCollection", "spaces", "triggersActionsUi", - "savedObjectsTaggingOss" + "savedObjectsTaggingOss", + "lens" ], "requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch", "savedSearch"], "extraPublicDirs": ["common"], diff --git a/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts b/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts index 803fb7c6f70db..a481c648aad20 100644 --- a/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts +++ b/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts @@ -18,6 +18,7 @@ const fields = [ }, { name: 'timestamp', + displayName: 'timestamp', type: 'date', scripted: false, filterable: true, @@ -26,12 +27,14 @@ const fields = [ }, { name: 'message', + displayName: 'message', type: 'string', scripted: false, filterable: false, }, { name: 'extension', + displayName: 'extension', type: 'string', scripted: false, filterable: true, @@ -39,6 +42,7 @@ const fields = [ }, { name: 'bytes', + displayName: 'bytes', type: 'number', scripted: false, filterable: true, @@ -46,6 +50,7 @@ const fields = [ }, { name: 'scripted', + displayName: 'scripted', type: 'number', scripted: true, filterable: false, diff --git a/src/plugins/discover/public/__mocks__/search_session.ts b/src/plugins/discover/public/__mocks__/search_session.ts index 9763ff7089e0a..abcd5e92a1cbd 100644 --- a/src/plugins/discover/public/__mocks__/search_session.ts +++ b/src/plugins/discover/public/__mocks__/search_session.ts @@ -10,11 +10,12 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DiscoverSearchSessionManager } from '../application/main/services/discover_search_session'; -export function createSearchSessionMock() { - const history = createMemoryHistory(); - const session = dataPluginMock.createStartContract().search.session as jest.Mocked< +export function createSearchSessionMock( + session = dataPluginMock.createStartContract().search.session as jest.Mocked< DataPublicPluginStart['search']['session'] - >; + > +) { + const history = createMemoryHistory(); const searchSessionManager = new DiscoverSearchSessionManager({ history, session, diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index a100f9888def4..d21bc4fc115b3 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -144,6 +144,7 @@ export function createDiscoverServicesMock(): DiscoverServices { savedObjectsTagging: {}, dataViews: dataPlugin.dataViews, timefilter: dataPlugin.query.timefilter.timefilter, + lens: { EmbeddableComponent: jest.fn(() => null) }, locator: { useUrl: jest.fn(() => ''), navigate: jest.fn(), diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index 56c0f349615e0..334e899b04aee 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -11,11 +11,9 @@ import { SearchSource } from '@kbn/data-plugin/common'; import { BehaviorSubject, Subject } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { action } from '@storybook/addon-actions'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { FetchStatus } from '../../../../types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, @@ -47,11 +45,6 @@ const documentObservables = { fetchStatus: FetchStatus.COMPLETE, result: Number(esHits.length), }) as DataTotalHits$, - - charts$: new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$, }; const plainRecordObservables = { @@ -77,11 +70,6 @@ const plainRecordObservables = { fetchStatus: FetchStatus.COMPLETE, recordRawType: RecordRawType.PLAIN, }) as DataTotalHits$, - - charts$: new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - recordRawType: RecordRawType.PLAIN, - }) as DataCharts$, }; const getCommonProps = (dataView: DataView) => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx new file mode 100644 index 0000000000000..5f2b0f9e434d7 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx @@ -0,0 +1,220 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { Subject, BehaviorSubject, of } from 'rxjs'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { esHits } from '../../../../__mocks__/es_hits'; +import { dataViewMock } from '../../../../__mocks__/data_view'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; +import { GetStateReturn } from '../../services/discover_state'; +import { + AvailableFields$, + DataDocuments$, + DataMain$, + DataTotalHits$, + RecordRawType, +} from '../../hooks/use_saved_search'; +import { discoverServiceMock } from '../../../../__mocks__/services'; +import { FetchStatus } from '../../../types'; +import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { buildDataTableRecord } from '../../../../utils/build_data_record'; +import { DiscoverHistogramLayout, DiscoverHistogramLayoutProps } from './discover_histogram_layout'; +import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { CoreTheme } from '@kbn/core/public'; +import { act } from 'react-dom/test-utils'; +import { setTimeout } from 'timers/promises'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; +import { HISTOGRAM_HEIGHT_KEY } from './use_discover_histogram'; +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { RequestAdapter } from '@kbn/inspector-plugin/public'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; +import { ResetSearchButton } from './reset_search_button'; + +const mountComponent = async ({ + isPlainRecord = false, + hideChart = false, + isTimeBased = true, + storage, + savedSearch = savedSearchMock, + resetSavedSearch = jest.fn(), +}: { + isPlainRecord?: boolean; + hideChart?: boolean; + isTimeBased?: boolean; + storage?: Storage; + savedSearch?: SavedSearch; + resetSavedSearch?(): void; +} = {}) => { + let services = discoverServiceMock; + services.data.query.timefilter.timefilter.getAbsoluteTime = () => { + return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; + }; + + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); + + if (storage) { + services = { ...services, storage }; + } + + const main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$; + + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewMock)), + }) as DataDocuments$; + + const availableFields$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$; + + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: Number(esHits.length), + }) as DataTotalHits$; + + const savedSearchData$ = { + main$, + documents$, + totalHits$, + availableFields$, + }; + + const session = getSessionServiceMock(); + + session.getSession$.mockReturnValue(new BehaviorSubject('123')); + + const props: DiscoverHistogramLayoutProps = { + isPlainRecord, + dataView: dataViewMock, + navigateTo: jest.fn(), + setExpandedDoc: jest.fn(), + savedSearch, + savedSearchData$, + savedSearchRefetch$: new Subject(), + state: { columns: [], hideChart }, + stateContainer: { + setAppState: () => {}, + appStateContainer: { + getState: () => ({ + interval: 'auto', + }), + }, + } as unknown as GetStateReturn, + onFieldEdited: jest.fn(), + columns: [], + viewMode: VIEW_MODE.DOCUMENT_LEVEL, + onAddFilter: jest.fn(), + resetSavedSearch, + isTimeBased, + resizeRef: { current: null }, + searchSessionManager: createSearchSessionMock(session).searchSessionManager, + inspectorAdapters: { requests: new RequestAdapter() }, + }; + + const coreTheme$ = new BehaviorSubject({ darkMode: false }); + + const component = mountWithIntl( + + + + + + ); + + // DiscoverMainContent uses UnifiedHistogramLayout which + // is lazy loaded, so we need to wait for it to be loaded + await act(() => setTimeout(0)); + component.update(); + + return component; +}; + +describe('Discover histogram layout component', () => { + describe('topPanelHeight persistence', () => { + it('should try to get the initial topPanelHeight for UnifiedHistogramLayout from storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + }); + + it('should pass undefined to UnifiedHistogramLayout if no value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(null); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(undefined); + }); + + it('should pass the stored topPanelHeight to UnifiedHistogramLayout if a value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const topPanelHeight = 123; + storage.get = jest.fn().mockImplementation(() => topPanelHeight); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(topPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(topPanelHeight); + }); + + it('should update the topPanelHeight in storage and pass the new value to UnifiedHistogramLayout when the topPanelHeight changes', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalSet = storage.set; + storage.set = jest.fn().mockImplementation(originalSet); + const component = await mountComponent({ storage }); + const newTopPanelHeight = 123; + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).not.toBe( + newTopPanelHeight + ); + act(() => { + component.find(UnifiedHistogramLayout).prop('onTopPanelHeightChange')!(newTopPanelHeight); + }); + component.update(); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(newTopPanelHeight); + }); + }); + + describe('reset search button', () => { + it('renders the button when there is a saved search', async () => { + const component = await mountComponent(); + expect(component.find(ResetSearchButton).exists()).toBe(true); + }); + + it('does not render the button when there is no saved search', async () => { + const component = await mountComponent({ + savedSearch: { ...savedSearchMock, id: undefined }, + }); + expect(component.find(ResetSearchButton).exists()).toBe(false); + }); + + it('should call resetSavedSearch when clicked', async () => { + const resetSavedSearch = jest.fn(); + const component = await mountComponent({ resetSavedSearch }); + component.find(ResetSearchButton).find('button').simulate('click'); + expect(resetSavedSearch).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx new file mode 100644 index 0000000000000..e6225a26ffea1 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx @@ -0,0 +1,87 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { RefObject } from 'react'; +import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; +import { css } from '@emotion/react'; +import { useDiscoverServices } from '../../../../hooks/use_discover_services'; +import { useDiscoverHistogram } from './use_discover_histogram'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import { type DiscoverMainContentProps, DiscoverMainContent } from './discover_main_content'; +import { ResetSearchButton } from './reset_search_button'; + +export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { + resetSavedSearch: () => void; + isTimeBased: boolean; + resizeRef: RefObject; + inspectorAdapters: InspectorAdapters; + searchSessionManager: DiscoverSearchSessionManager; +} + +export const DiscoverHistogramLayout = ({ + isPlainRecord, + dataView, + resetSavedSearch, + savedSearch, + savedSearchData$, + state, + stateContainer, + isTimeBased, + resizeRef, + inspectorAdapters, + searchSessionManager, + ...mainContentProps +}: DiscoverHistogramLayoutProps) => { + const services = useDiscoverServices(); + + const commonProps = { + dataView, + isPlainRecord, + stateContainer, + savedSearch, + state, + savedSearchData$, + }; + + const histogramProps = useDiscoverHistogram({ + isTimeBased, + inspectorAdapters, + searchSessionManager, + ...commonProps, + }); + + if (!histogramProps) { + return null; + } + + const histogramLayoutCss = css` + height: 100%; + `; + + return ( + : undefined + } + css={histogramLayoutCss} + {...histogramProps} + > + + + ); +}; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss index 1d314cc72efb4..a65c22b57b2ab 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss @@ -45,11 +45,9 @@ discover-app { } .dscPageContent { + position: relative; + overflow: hidden; border: $euiBorderThin; -} - -.dscPageContent, -.dscPageContent__inner { height: 100%; } diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index fe631f16985b8..5b58cda5e0b96 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Subject, BehaviorSubject } from 'rxjs'; +import { Subject, BehaviorSubject, of } from 'rxjs'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { Query, AggregateQuery } from '@kbn/es-query'; import { setHeaderActionMenuMounter } from '../../../../kibana_services'; @@ -15,14 +15,16 @@ import { DiscoverLayout, SIDEBAR_CLOSED_KEY } from './discover_layout'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; -import { createSearchSourceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { + createSearchSourceMock, + searchSourceInstanceMock, +} from '@kbn/data-plugin/common/search/search_source/mocks'; import type { DataView } from '@kbn/data-views-plugin/public'; import { dataViewWithTimefieldMock } from '../../../../__mocks__/data_view_with_timefield'; import { GetStateReturn } from '../../services/discover_state'; import { DiscoverLayoutProps } from './types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, @@ -37,66 +39,11 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { DiscoverServices } from '../../../../build_services'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; -import type { UnifiedHistogramChartData } from '@kbn/unified-histogram-plugin/public'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { setTimeout } from 'timers/promises'; import { act } from 'react-dom/test-utils'; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; - - return { - ...originalModule, - buildChartData: jest.fn().mockImplementation(() => ({ - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - })), - }; -}); +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; function getAppStateContainer() { const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; @@ -124,6 +71,14 @@ async function mountComponent( }) as unknown as Storage, } as unknown as DiscoverServices; + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); + const dataViewList = [dataView]; const main$ = new BehaviorSubject({ @@ -147,19 +102,17 @@ async function mountComponent( result: Number(esHits.length), }) as DataTotalHits$; - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; + const session = getSessionServiceMock(); + + session.getSession$.mockReturnValue(new BehaviorSubject('123')); + const props = { dataView, dataViewList, @@ -172,7 +125,7 @@ async function mountComponent( savedSearchData$, savedSearchRefetch$: new Subject(), searchSource: searchSourceMock, - state: { columns: [], query }, + state: { columns: [], query, hideChart: false, interval: 'auto' }, stateContainer: { setAppState: () => {}, appStateContainer: { @@ -185,6 +138,7 @@ async function mountComponent( persistDataView: jest.fn(), updateAdHocDataViewId: jest.fn(), adHocDataViewList: [], + searchSessionManager: createSearchSessionMock(session).searchSessionManager, savedDataViewList: [], updateDataViewList: jest.fn(), }; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 7659407d35369..d8c5445fd5409 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -43,7 +43,7 @@ import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { hasActiveFilter } from './utils'; import { getRawRecordType } from '../../utils/get_raw_record_type'; import { SavedSearchURLConflictCallout } from '../../../../components/saved_search_url_conflict_callout/saved_search_url_conflict_callout'; -import { DiscoverMainContent } from './discover_main_content'; +import { DiscoverHistogramLayout } from './discover_histogram_layout'; /** * Local storage key for sidebar persistence state @@ -72,6 +72,7 @@ export function DiscoverLayout({ persistDataView, updateAdHocDataViewId, adHocDataViewList, + searchSessionManager, savedDataViewList, updateDataViewList, }: DiscoverLayoutProps) { @@ -197,6 +198,75 @@ export function DiscoverLayout({ const resizeRef = useRef(null); + const mainDisplay = useMemo(() => { + if (resultState === 'none') { + return ( + + ); + } + + if (resultState === 'uninitialized') { + return savedSearchRefetch$.next(undefined)} />; + } + + return ( + <> + + {resultState === 'loading' && } + + ); + }, [ + columns, + data, + dataState.error, + dataView, + expandedDoc, + inspectorAdapters, + isPlainRecord, + isTimeBased, + navigateTo, + onAddFilter, + onDisableFilters, + onFieldEdited, + resetSavedSearch, + resultState, + savedSearch, + savedSearchData$, + savedSearchRefetch$, + searchSessionManager, + setExpandedDoc, + state, + stateContainer, + viewMode, + ]); + return (

- {resultState === 'none' && ( - - )} - {resultState === 'uninitialized' && ( - savedSearchRefetch$.next(undefined)} /> - )} - {resultState === 'loading' && } - {resultState === 'ready' && ( - - )} + {mainDisplay} diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index 6f60055537656..dd30d6b119fd3 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -7,15 +7,14 @@ */ import React from 'react'; -import { Subject, BehaviorSubject } from 'rxjs'; -import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; +import { Subject, BehaviorSubject, of } from 'rxjs'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; -import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { GetStateReturn } from '../../services/discover_state'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, @@ -26,95 +25,31 @@ import { FetchStatus } from '../../../types'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { DiscoverMainContent, DiscoverMainContentProps } from './discover_main_content'; -import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; import { CoreTheme } from '@kbn/core/public'; import { act } from 'react-dom/test-utils'; import { setTimeout } from 'timers/promises'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; -import { - UnifiedHistogramChartData, - UnifiedHistogramLayout, -} from '@kbn/unified-histogram-plugin/public'; -import { HISTOGRAM_HEIGHT_KEY } from './use_discover_histogram'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; - - return { - ...originalModule, - buildChartData: jest.fn().mockImplementation(() => ({ - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - })), - }; -}); +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { DiscoverDocuments } from './discover_documents'; +import { FieldStatisticsTab } from '../field_stats_table'; const mountComponent = async ({ isPlainRecord = false, - hideChart = false, - isTimeBased = true, - storage, - savedSearch = savedSearchMock, - resetSavedSearch = jest.fn(), + viewMode = VIEW_MODE.DOCUMENT_LEVEL, }: { isPlainRecord?: boolean; - hideChart?: boolean; - isTimeBased?: boolean; - storage?: Storage; - savedSearch?: SavedSearch; - resetSavedSearch?: () => void; + viewMode?: VIEW_MODE; } = {}) => { - let services = createDiscoverServicesMock(); + const services = createDiscoverServicesMock(); - if (storage) { - services = { ...services, storage }; - } + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, @@ -137,16 +72,10 @@ const mountComponent = async ({ result: Number(esHits.length), }) as DataTotalHits$; - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; @@ -154,12 +83,11 @@ const mountComponent = async ({ isPlainRecord, dataView: dataViewMock, navigateTo: jest.fn(), - resetSavedSearch, setExpandedDoc: jest.fn(), - savedSearch, + savedSearch: savedSearchMock, savedSearchData$, savedSearchRefetch$: new Subject(), - state: { columns: [], hideChart }, + state: { columns: [], hideChart: false }, stateContainer: { setAppState: () => {}, appStateContainer: { @@ -168,12 +96,10 @@ const mountComponent = async ({ }), }, } as unknown as GetStateReturn, - isTimeBased, - viewMode: VIEW_MODE.DOCUMENT_LEVEL, - onAddFilter: jest.fn(), onFieldEdited: jest.fn(), columns: [], - resizeRef: { current: null }, + viewMode, + onAddFilter: jest.fn(), }; const coreTheme$ = new BehaviorSubject({ darkMode: false }); @@ -189,6 +115,7 @@ const mountComponent = async ({ // DiscoverMainContent uses UnifiedHistogramLayout which // is lazy loaded, so we need to wait for it to be loaded await act(() => setTimeout(0)); + component.update(); return component; }; @@ -197,82 +124,26 @@ describe('Discover main content component', () => { describe('DocumentViewModeToggle', () => { it('should show DocumentViewModeToggle when isPlainRecord is false', async () => { const component = await mountComponent(); - component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(true); }); it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => { const component = await mountComponent({ isPlainRecord: true }); - component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(false); }); }); - describe('topPanelHeight persistence', () => { - it('should try to get the initial topPanelHeight for UnifiedHistogramLayout from storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalGet = storage.get; - storage.get = jest.fn().mockImplementation(originalGet); - await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - }); - - it('should pass undefined to UnifiedHistogramLayout if no value is found in storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalGet = storage.get; - storage.get = jest.fn().mockImplementation(originalGet); - const component = await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(storage.get).toHaveReturnedWith(null); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(undefined); - }); - - it('should pass the stored topPanelHeight to UnifiedHistogramLayout if a value is found in storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const topPanelHeight = 123; - storage.get = jest.fn().mockImplementation(() => topPanelHeight); - const component = await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(storage.get).toHaveReturnedWith(topPanelHeight); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(topPanelHeight); - }); - - it('should update the topPanelHeight in storage and pass the new value to UnifiedHistogramLayout when the topPanelHeight changes', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalSet = storage.set; - storage.set = jest.fn().mockImplementation(originalSet); - const component = await mountComponent({ storage }); - const newTopPanelHeight = 123; - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).not.toBe( - newTopPanelHeight - ); - act(() => { - component.find(UnifiedHistogramLayout).prop('onTopPanelHeightChange')!(newTopPanelHeight); - }); - component.update(); - expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(newTopPanelHeight); - }); - }); - - describe('reset search button', () => { - it('renders the button when there is a saved search', async () => { + describe('Document view', () => { + it('should show DiscoverDocuments when VIEW_MODE is DOCUMENT_LEVEL', async () => { const component = await mountComponent(); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(1); - }); - - it('does not render the button when there is no saved search', async () => { - const component = await mountComponent({ - savedSearch: { ...savedSearchMock, id: undefined }, - }); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(0); + expect(component.find(DiscoverDocuments).exists()).toBe(true); + expect(component.find(FieldStatisticsTab).exists()).toBe(false); }); - it('should call resetSavedSearch when clicked', async () => { - const resetSavedSearch = jest.fn(); - const component = await mountComponent({ resetSavedSearch }); - findTestSubject(component, 'resetSavedSearch').simulate('click'); - expect(resetSavedSearch).toHaveBeenCalled(); + it('should show FieldStatisticsTableMemoized when VIEW_MODE is not DOCUMENT_LEVEL', async () => { + const component = await mountComponent({ viewMode: VIEW_MODE.AGGREGATED_LEVEL }); + expect(component.find(DiscoverDocuments).exists()).toBe(false); + expect(component.find(FieldStatisticsTab).exists()).toBe(true); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index 86428fff1ed91..98b15fe9e5999 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -6,14 +6,11 @@ * Side Public License, v 1. */ -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import React, { RefObject, useCallback } from 'react'; +import React, { useCallback } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { METRIC_TYPE } from '@kbn/analytics'; -import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DataTableRecord } from '../../../../types'; import { DocumentViewModeToggle, VIEW_MODE } from '../../../../components/view_mode_toggle'; @@ -23,49 +20,41 @@ import { AppState, GetStateReturn } from '../../services/discover_state'; import { FieldStatisticsTab } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; import { DOCUMENTS_VIEW_CLICK, FIELD_STATISTICS_VIEW_CLICK } from '../field_stats_table/constants'; -import { useDiscoverHistogram } from './use_discover_histogram'; export interface DiscoverMainContentProps { - isPlainRecord: boolean; dataView: DataView; - navigateTo: (url: string) => void; - resetSavedSearch: () => void; - expandedDoc?: DataTableRecord; - setExpandedDoc: (doc?: DataTableRecord) => void; savedSearch: SavedSearch; + isPlainRecord: boolean; + navigateTo: (url: string) => void; savedSearchData$: SavedSearchData; savedSearchRefetch$: DataRefetch$; - state: AppState; - stateContainer: GetStateReturn; - isTimeBased: boolean; + expandedDoc?: DataTableRecord; + setExpandedDoc: (doc?: DataTableRecord) => void; viewMode: VIEW_MODE; onAddFilter: DocViewFilterFn | undefined; onFieldEdited: () => Promise; columns: string[]; - resizeRef: RefObject; + state: AppState; + stateContainer: GetStateReturn; } export const DiscoverMainContent = ({ - isPlainRecord, dataView, + isPlainRecord, navigateTo, - resetSavedSearch, - expandedDoc, - setExpandedDoc, - savedSearch, savedSearchData$, savedSearchRefetch$, - state, - stateContainer, - isTimeBased, + expandedDoc, + setExpandedDoc, viewMode, onAddFilter, onFieldEdited, columns, - resizeRef, + state, + stateContainer, + savedSearch, }: DiscoverMainContentProps) => { - const services = useDiscoverServices(); - const { trackUiMetric } = services; + const { trackUiMetric } = useDiscoverServices(); const setDiscoverViewMode = useCallback( (mode: VIEW_MODE) => { @@ -82,96 +71,45 @@ export const DiscoverMainContent = ({ [trackUiMetric, stateContainer] ); - const { - topPanelHeight, - hits, - chart, - onEditVisualization, - onTopPanelHeightChange, - onChartHiddenChange, - onTimeIntervalChange, - } = useDiscoverHistogram({ - stateContainer, - state, - savedSearchData$, - dataView, - savedSearch, - isTimeBased, - isPlainRecord, - }); - return ( - - - - - - ) : undefined - } - onTopPanelHeightChange={onTopPanelHeightChange} - onEditVisualization={onEditVisualization} - onChartHiddenChange={onChartHiddenChange} - onTimeIntervalChange={onTimeIntervalChange} + - - {!isPlainRecord && ( - - - - - )} - {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( - - ) : ( - - )} - - + {!isPlainRecord && ( + + + + + )} + {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( + + ) : ( + + )} + ); }; diff --git a/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx b/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx new file mode 100644 index 0000000000000..cde96ff72050f --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx @@ -0,0 +1,20 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import React from 'react'; +import { ResetSearchButton } from './reset_search_button'; + +describe('ResetSearchButton', () => { + it('should call resetSavedSearch when the button is clicked', () => { + const resetSavedSearch = jest.fn(); + const component = mountWithIntl(); + component.find('button[data-test-subj="resetSavedSearch"]').simulate('click'); + expect(resetSavedSearch).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx b/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx new file mode 100644 index 0000000000000..e9b0cc2417d97 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx @@ -0,0 +1,35 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButtonEmpty, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { css } from '@emotion/react'; + +const resetSearchButtonWrapper = css` + overflow: hidden; +`; + +export const ResetSearchButton = ({ resetSavedSearch }: { resetSavedSearch?: () => void }) => { + return ( + + + + + + ); +}; diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index 2ce822b28d150..24b0a47f6f2a6 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -9,16 +9,17 @@ import type { Query, TimeRange, AggregateQuery } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataViewListItem, ISearchSource } from '@kbn/data-plugin/public'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { AppState, GetStateReturn } from '../../services/discover_state'; import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; export interface DiscoverLayoutProps { dataView: DataView; dataViewList: DataViewListItem[]; - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; navigateTo: (url: string) => void; onChangeDataView: (id: string) => void; onUpdateQuery: ( @@ -38,5 +39,6 @@ export interface DiscoverLayoutProps { updateDataViewList: (dataViews: DataView[]) => Promise; updateAdHocDataViewId: (dataView: DataView) => Promise; adHocDataViewList: DataView[]; + searchSessionManager: DiscoverSearchSessionManager; savedDataViewList: DataViewListItem[]; } diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts index 0306c36ce3482..b562ed1f6df07 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { esHits } from '../../../../__mocks__/es_hits'; import { act, renderHook } from '@testing-library/react-hooks'; @@ -14,13 +13,12 @@ import { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../../types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, RecordRawType, } from '../../hooks/use_saved_search'; -import type { GetStateReturn } from '../../services/discover_state'; +import type { AppState, GetStateReturn } from '../../services/discover_state'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; @@ -33,7 +31,14 @@ import { } from './use_discover_histogram'; import { setTimeout } from 'timers/promises'; import { calculateBounds } from '@kbn/data-plugin/public'; -import { buildChartData } from '@kbn/unified-histogram-plugin/public'; +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { RequestAdapter } from '@kbn/inspector-plugin/public'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; +import { UnifiedHistogramFetchStatus } from '@kbn/unified-histogram-plugin/public'; +import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_messages'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import { DiscoverSearchSessionManager } from '../../services/discover_search_session'; const mockData = dataPluginMock.createStartContract(); @@ -44,6 +49,10 @@ mockData.query.timefilter.timefilter.calculateBounds = (timeRange) => { return calculateBounds(timeRange); }; +const mockLens = { + navigateToPrefilledEditor: jest.fn(), +}; + let mockStorage = new LocalStorageMock({}) as unknown as Storage; let mockCanVisualize = true; @@ -51,7 +60,7 @@ jest.mock('../../../../hooks/use_discover_services', () => { const originalModule = jest.requireActual('../../../../hooks/use_discover_services'); return { ...originalModule, - useDiscoverServices: () => ({ storage: mockStorage, data: mockData }), + useDiscoverServices: () => ({ storage: mockStorage, data: mockData, lens: mockLens }), }; }); @@ -63,39 +72,53 @@ jest.mock('@kbn/unified-field-list-plugin/public', () => { }; }); -const mockBuildChartData = buildChartData as jest.MockedFunction; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); +jest.mock('../../hooks/use_saved_search_messages', () => { + const originalModule = jest.requireActual('../../hooks/use_saved_search_messages'); return { ...originalModule, - buildChartData: jest.fn(originalModule.buildChartData), + checkHitCount: jest.fn(originalModule.checkHitCount), + sendErrorTo: jest.fn(originalModule.sendErrorTo), }; }); +const mockCheckHitCount = checkHitCount as jest.MockedFunction; + describe('useDiscoverHistogram', () => { const renderUseDiscoverHistogram = async ({ isPlainRecord = false, isTimeBased = true, canVisualize = true, storage = new LocalStorageMock({}) as unknown as Storage, + state = { interval: 'auto', hideChart: false, breakdownField: 'extension' }, stateContainer = {}, + searchSessionManager, + searchSessionId = '123', + inspectorAdapters = { requests: new RequestAdapter() }, + totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: Number(esHits.length), + }) as DataTotalHits$, + main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$, }: { isPlainRecord?: boolean; isTimeBased?: boolean; canVisualize?: boolean; storage?: Storage; + state?: AppState; stateContainer?: unknown; + searchSessionManager?: DiscoverSearchSessionManager; + searchSessionId?: string | null; + inspectorAdapters?: InspectorAdapters; + totalHits$?: DataTotalHits$; + main$?: DataMain$; } = {}) => { mockStorage = storage; mockCanVisualize = canVisualize; - const main$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, - foundDocuments: true, - }) as DataMain$; - const documents$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewWithTimefieldMock)), @@ -106,148 +129,142 @@ describe('useDiscoverHistogram', () => { fields: [] as string[], }) as AvailableFields$; - const totalHits$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - result: Number(esHits.length), - }) as DataTotalHits$; - - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: { - took: 0, - timed_out: false, - _shards: { - total: 1, - successful: 1, - skipped: 0, - failed: 0, - }, - hits: { - total: 29, - max_score: null, - hits: [], - }, - aggregations: { - '2': { - buckets: [ - { - key_as_string: '2022-10-05T16:00:00.000-03:00', - key: 1664996400000, - doc_count: 6, - }, - { - key_as_string: '2022-10-05T16:30:00.000-03:00', - key: 1664998200000, - doc_count: 2, - }, - { - key_as_string: '2022-10-05T17:00:00.000-03:00', - key: 1665000000000, - doc_count: 3, - }, - { - key_as_string: '2022-10-05T17:30:00.000-03:00', - key: 1665001800000, - doc_count: 8, - }, - { - key_as_string: '2022-10-05T18:00:00.000-03:00', - key: 1665003600000, - doc_count: 10, - }, - ], - }, - }, - } as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; - const hook = renderHook(() => { - return useDiscoverHistogram({ - stateContainer: stateContainer as GetStateReturn, - state: { interval: 'auto', hideChart: false }, - savedSearchData$, - dataView: dataViewWithTimefieldMock, - savedSearch: savedSearchMock, - isTimeBased, - isPlainRecord, - }); - }); + if (!searchSessionManager) { + const session = getSessionServiceMock(); + session.getSession$.mockReturnValue(new BehaviorSubject(searchSessionId ?? undefined)); + searchSessionManager = createSearchSessionMock(session).searchSessionManager; + } + + const initialProps = { + stateContainer: stateContainer as GetStateReturn, + state, + savedSearchData$, + dataView: dataViewWithTimefieldMock, + savedSearch: savedSearchMock, + isTimeBased, + isPlainRecord, + inspectorAdapters, + searchSessionManager: searchSessionManager!, + }; + + const hook = renderHook( + (props: Parameters[0]) => useDiscoverHistogram(props), + { initialProps } + ); await act(() => setTimeout(0)); - return hook; + return { hook, initialProps }; }; - const expectedChartData = { - xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], - xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, - xAxisLabel: 'timestamp per 0 milliseconds', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: 'P0D', - intervalESUnit: 'ms', - intervalESValue: 0, - min: '1991-03-29T08:04:00.694Z', - max: '2021-03-29T07:04:00.695Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1664996400000, y: 6 }, - { x: 1664998200000, y: 2 }, - { x: 1665000000000, y: 3 }, - { x: 1665001800000, y: 8 }, - { x: 1665003600000, y: 10 }, - ], - }; + it('should return undefined if there is no search session', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ searchSessionId: null }); + expect(result.current).toBeUndefined(); + }); describe('contexts', () => { it('should output the correct hits context', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.hits?.status).toBe(FetchStatus.COMPLETE); - expect(result.current.hits?.total).toEqual(esHits.length); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.complete); + expect(result.current?.hits?.total).toEqual(esHits.length); }); it('should output the correct chart context', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.chart?.status).toBe(FetchStatus.COMPLETE); - expect(result.current.chart?.hidden).toBe(false); - expect(result.current.chart?.timeInterval).toBe('auto'); - expect(result.current.chart?.bucketInterval?.toString()).toBe('P0D'); - expect(JSON.stringify(result.current.chart?.data)).toBe(JSON.stringify(expectedChartData)); - expect(result.current.chart?.error).toBeUndefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.chart?.hidden).toBe(false); + expect(result.current?.chart?.timeInterval).toBe('auto'); + }); + + it('should output the correct breakdown context', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.breakdown?.field?.name).toBe('extension'); }); - it('should output undefined for hits and chart if isPlainRecord is true', async () => { - const { result } = await renderUseDiscoverHistogram({ isPlainRecord: true }); - expect(result.current.hits).toBeUndefined(); - expect(result.current.chart).toBeUndefined(); + it('should output the correct request context', async () => { + const requestAdapter = new RequestAdapter(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ + searchSessionId: '321', + inspectorAdapters: { requests: requestAdapter }, + }); + expect(result.current?.request.adapter).toBe(requestAdapter); + expect(result.current?.request.searchSessionId).toBe('321'); }); - it('should output undefined for chart if isTimeBased is false', async () => { - const { result } = await renderUseDiscoverHistogram({ isTimeBased: false }); - expect(result.current.hits).not.toBeUndefined(); - expect(result.current.chart).toBeUndefined(); + it('should output undefined for hits and chart and breakdown if isPlainRecord is true', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ isPlainRecord: true }); + expect(result.current?.hits).toBeUndefined(); + expect(result.current?.chart).toBeUndefined(); + expect(result.current?.breakdown).toBeUndefined(); + }); + + it('should output undefined for chart and breakdown if isTimeBased is false', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ isTimeBased: false }); + expect(result.current?.hits).not.toBeUndefined(); + expect(result.current?.chart).toBeUndefined(); + expect(result.current?.breakdown).toBeUndefined(); + }); + + it('should clear lensRequests when chart is undefined', async () => { + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { hook, initialProps } = await renderUseDiscoverHistogram({ + inspectorAdapters, + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + hook.rerender({ ...initialProps, isPlainRecord: true }); + expect(inspectorAdapters.lensRequests).toBeUndefined(); }); }); describe('onEditVisualization', () => { it('returns a callback for onEditVisualization when the data view can be visualized', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.onEditVisualization).toBeDefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.onEditVisualization).toBeDefined(); }); it('returns undefined for onEditVisualization when the data view cannot be visualized', async () => { - const { result } = await renderUseDiscoverHistogram({ canVisualize: false }); - expect(result.current.onEditVisualization).toBeUndefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ canVisualize: false }); + expect(result.current?.onEditVisualization).toBeUndefined(); + }); + + it('should call lens.navigateToPrefilledEditor when onEditVisualization is called', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + const attributes = { title: 'test' } as TypedLensByValueInput['attributes']; + result.current?.onEditVisualization!(attributes); + expect(mockLens.navigateToPrefilledEditor).toHaveBeenCalledWith({ + id: '', + timeRange: mockData.query.timefilter.timefilter.getTime(), + attributes, + }); }); }); @@ -255,38 +272,104 @@ describe('useDiscoverHistogram', () => { it('should try to get the topPanelHeight from storage', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.get = jest.fn(() => 100); - const { result } = await renderUseDiscoverHistogram({ storage }); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage }); expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(result.current.topPanelHeight).toBe(100); + expect(result.current?.topPanelHeight).toBe(100); }); it('should update topPanelHeight when onTopPanelHeightChange is called', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.get = jest.fn(() => 100); storage.set = jest.fn(); - const { result } = await renderUseDiscoverHistogram({ storage }); - expect(result.current.topPanelHeight).toBe(100); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage }); + expect(result.current?.topPanelHeight).toBe(100); act(() => { - result.current.onTopPanelHeightChange(200); + result.current?.onTopPanelHeightChange(200); }); expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, 200); - expect(result.current.topPanelHeight).toBe(200); + expect(result.current?.topPanelHeight).toBe(200); }); }); describe('callbacks', () => { it('should update chartHidden when onChartHiddenChange is called', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + storage.set = jest.fn(); + const state = { interval: 'auto', hideChart: false, breakdownField: 'extension' }; + const stateContainer = { + setAppState: jest.fn((newState) => { + Object.assign(state, newState); + }), + }; + const session = getSessionServiceMock(); + const session$ = new BehaviorSubject('123'); + session.getSession$.mockReturnValue(session$); + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { hook } = await renderUseDiscoverHistogram({ + storage, + state, + stateContainer, + searchSessionManager: createSearchSessionMock(session).searchSessionManager, + inspectorAdapters, + }); + act(() => { + hook.result.current?.onChartHiddenChange(false); + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, false); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: false }); + act(() => { + hook.result.current?.onChartHiddenChange(true); + session$.next('321'); + }); + hook.rerender(); + expect(inspectorAdapters.lensRequests).toBeUndefined(); + expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, true); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: true }); + }); + + it('should set lensRequests when onChartLoad is called', async () => { + const lensRequests = new RequestAdapter(); + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: undefined as RequestAdapter | undefined, + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ inspectorAdapters }); + expect(inspectorAdapters.lensRequests).toBeUndefined(); + act(() => { + result.current?.onChartLoad({ complete: true, adapters: { requests: lensRequests } }); + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + }); + + it('should update chart hidden when onChartHiddenChange is called', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.set = jest.fn(); const stateContainer = { setAppState: jest.fn(), }; - const { result } = await renderUseDiscoverHistogram({ + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage, stateContainer, + inspectorAdapters, }); act(() => { - result.current.onChartHiddenChange(true); + result.current?.onChartHiddenChange(true); }); expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, true); expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: true }); @@ -296,33 +379,99 @@ describe('useDiscoverHistogram', () => { const stateContainer = { setAppState: jest.fn(), }; - const { result } = await renderUseDiscoverHistogram({ + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ stateContainer, }); act(() => { - result.current.onTimeIntervalChange('auto'); + result.current?.onTimeIntervalChange('auto'); }); expect(stateContainer.setAppState).toHaveBeenCalledWith({ interval: 'auto' }); }); - }); - describe('buildChartData', () => { - it('should call buildChartData when isPlainRecord is false and isTimeBased is true', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram(); - expect(mockBuildChartData).toHaveBeenCalled(); + it('should update breakdownField when onBreakdownFieldChange is called', async () => { + const stateContainer = { + setAppState: jest.fn(), + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ + stateContainer, + }); + act(() => { + result.current?.onBreakdownFieldChange( + dataViewWithTimefieldMock.getFieldByName('extension') + ); + }); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ breakdownField: 'extension' }); }); - it('should not call buildChartData when isPlainRecord is true', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram({ isPlainRecord: true }); - expect(mockBuildChartData).not.toHaveBeenCalled(); + it('should update total hits when onTotalHitsChange is called', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.LOADING, + result: undefined, + }) as DataTotalHits$; + const main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$, main$ }); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.complete, 100); + }); + hook.rerender(); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.complete); + expect(hook.result.current?.hits?.total).toBe(100); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.COMPLETE, + result: 100, + }); + expect(mockCheckHitCount).toHaveBeenCalledWith(main$, 100); }); - it('should not call buildChartData when isTimeBased is false', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram({ isTimeBased: false }); - expect(mockBuildChartData).not.toHaveBeenCalled(); + it('should not update total hits when onTotalHitsChange is called with an error', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.UNINITIALIZED, + result: undefined, + }) as DataTotalHits$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$ }); + const error = new Error('test'); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.error, error); + }); + hook.rerender(); + expect(sendErrorTo).toHaveBeenCalledWith(mockData, totalHits$); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.error); + expect(hook.result.current?.hits?.total).toBeUndefined(); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.ERROR, + error, + }); + expect(mockCheckHitCount).not.toHaveBeenCalled(); + }); + + it('should not update total hits when onTotalHitsChange is called with a loading status while totalHits$ has a partial status', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.PARTIAL, + result: undefined, + }) as DataTotalHits$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$ }); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.loading, undefined); + }); + hook.rerender(); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.partial); + expect(hook.result.current?.hits?.total).toBeUndefined(); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.PARTIAL, + result: undefined, + }); + expect(mockCheckHitCount).not.toHaveBeenCalled(); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts index 91c641a38cb08..2141ab8cd21ef 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -6,23 +6,30 @@ * Side Public License, v 1. */ -import type { DataView } from '@kbn/data-views-plugin/common'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import type { SavedSearch } from '@kbn/saved-search-plugin/public'; -import { - getVisualizeInformation, - triggerVisualizeActions, -} from '@kbn/unified-field-list-plugin/public'; -import { buildChartData } from '@kbn/unified-histogram-plugin/public'; +import { getVisualizeInformation } from '@kbn/unified-field-list-plugin/public'; import { useCallback, useEffect, useMemo, useState } from 'react'; +import { + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, +} from '@kbn/unified-histogram-plugin/public'; +import type { UnifiedHistogramChartLoadEvent } from '@kbn/unified-histogram-plugin/public'; +import useObservable from 'react-use/lib/useObservable'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { getUiActions } from '../../../../kibana_services'; -import { PLUGIN_ID } from '../../../../../common'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { useDataState } from '../../hooks/use_data_state'; import type { SavedSearchData } from '../../hooks/use_saved_search'; import type { AppState, GetStateReturn } from '../../services/discover_state'; +import { FetchStatus } from '../../../types'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_messages'; export const CHART_HIDDEN_KEY = 'discover:chartHidden'; export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight'; +export const HISTOGRAM_BREAKDOWN_FIELD_KEY = 'discover:histogramBreakdownField'; export const useDiscoverHistogram = ({ stateContainer, @@ -32,6 +39,8 @@ export const useDiscoverHistogram = ({ savedSearch, isTimeBased, isPlainRecord, + inspectorAdapters, + searchSessionManager, }: { stateContainer: GetStateReturn; state: AppState; @@ -40,8 +49,10 @@ export const useDiscoverHistogram = ({ savedSearch: SavedSearch; isTimeBased: boolean; isPlainRecord: boolean; + inspectorAdapters: InspectorAdapters; + searchSessionManager: DiscoverSearchSessionManager; }) => { - const { storage, data } = useDiscoverServices(); + const { storage, data, lens } = useDiscoverServices(); /** * Visualize @@ -65,18 +76,19 @@ export const useDiscoverHistogram = ({ }); }, [dataView, savedSearch.columns, timeField]); - const onEditVisualization = useCallback(() => { - if (!timeField) { - return; - } - triggerVisualizeActions( - getUiActions(), - timeField, - savedSearch.columns || [], - PLUGIN_ID, - dataView - ); - }, [dataView, savedSearch.columns, timeField]); + const onEditVisualization = useCallback( + (lensAttributes: TypedLensByValueInput['attributes']) => { + if (!timeField) { + return; + } + lens.navigateToPrefilledEditor({ + id: '', + timeRange: data.query.timefilter.timefilter.getTime(), + attributes: lensAttributes, + }); + }, + [data.query.timefilter.timefilter, lens, timeField] + ); /** * Height @@ -96,17 +108,9 @@ export const useDiscoverHistogram = ({ ); /** - * Other callbacks + * Time interval */ - const onChartHiddenChange = useCallback( - (chartHidden: boolean) => { - storage.set(CHART_HIDDEN_KEY, chartHidden); - stateContainer.setAppState({ hideChart: chartHidden }); - }, - [stateContainer, storage] - ); - const onTimeIntervalChange = useCallback( (newInterval: string) => { stateContainer.setAppState({ interval: newInterval }); @@ -115,9 +119,62 @@ export const useDiscoverHistogram = ({ ); /** - * Data + * Request + */ + + // The searchSessionId will be updated whenever a new search + // is started and will trigger a unified histogram refetch + const searchSessionId = useObservable(searchSessionManager.searchSessionId$); + const request = useMemo( + () => ({ + searchSessionId, + adapter: inspectorAdapters.requests, + }), + [inspectorAdapters.requests, searchSessionId] + ); + + /** + * Total hits */ + const [localHitsContext, setLocalHitsContext] = useState(); + + const onTotalHitsChange = useCallback( + (status: UnifiedHistogramFetchStatus, result?: number | Error) => { + if (result instanceof Error) { + // Display the error and set totalHits$ to an error state + sendErrorTo(data, savedSearchData$.totalHits$)(result); + return; + } + + const { fetchStatus, recordRawType } = savedSearchData$.totalHits$.getValue(); + + // If we have a partial result already, we don't want to update the total hits back to loading + if (fetchStatus === FetchStatus.PARTIAL && status === UnifiedHistogramFetchStatus.loading) { + return; + } + + // Set a local copy of the hits context to pass to unified histogram + setLocalHitsContext({ status, total: result }); + + // Sync the totalHits$ observable with the unified histogram state + savedSearchData$.totalHits$.next({ + fetchStatus: status.toString() as FetchStatus, + result, + recordRawType, + }); + + // Check the hits count to set a partial or no results state + if (status === UnifiedHistogramFetchStatus.complete && typeof result === 'number') { + checkHitCount(savedSearchData$.main$, result); + } + }, + [data, savedSearchData$.main$, savedSearchData$.totalHits$] + ); + + // We only rely on the totalHits$ observable if we don't have a local hits context yet, + // since we only want to show the partial results on the first load, or there will be + // a flickering effect as the loading spinner is quickly shown and hidden again on fetches const { fetchStatus: hitsFetchStatus, result: hitsTotal } = useDataState( savedSearchData$.totalHits$ ); @@ -126,59 +183,96 @@ export const useDiscoverHistogram = ({ () => isPlainRecord ? undefined - : { - status: hitsFetchStatus, + : localHitsContext ?? { + status: hitsFetchStatus.toString() as UnifiedHistogramFetchStatus, total: hitsTotal, }, - [hitsFetchStatus, hitsTotal, isPlainRecord] + [hitsFetchStatus, hitsTotal, isPlainRecord, localHitsContext] ); - const { fetchStatus: chartFetchStatus, response, error } = useDataState(savedSearchData$.charts$); + /** + * Chart + */ - const { bucketInterval, chartData } = useMemo( - () => - isPlainRecord || !isTimeBased - ? { bucketInterval: undefined, chartData: undefined } - : buildChartData({ - data, - dataView, - timeInterval: state.interval, - response, - }), - [data, dataView, isPlainRecord, isTimeBased, response, state.interval] + const onChartHiddenChange = useCallback( + (chartHidden: boolean) => { + storage.set(CHART_HIDDEN_KEY, chartHidden); + stateContainer.setAppState({ hideChart: chartHidden }); + }, + [stateContainer, storage] + ); + + const onChartLoad = useCallback( + (event: UnifiedHistogramChartLoadEvent) => { + // We need to store the Lens request adapter in order to inspect its requests + inspectorAdapters.lensRequests = event.adapters.requests; + }, + [inspectorAdapters] ); + const [chartHidden, setChartHidden] = useState(state.hideChart); const chart = useMemo( () => isPlainRecord || !isTimeBased ? undefined : { - status: chartFetchStatus, - hidden: state.hideChart, + hidden: chartHidden, timeInterval: state.interval, - bucketInterval, - data: chartData, - error, }, - [ - bucketInterval, - chartData, - chartFetchStatus, - error, - isPlainRecord, - isTimeBased, - state.hideChart, - state.interval, - ] + [chartHidden, isPlainRecord, isTimeBased, state.interval] + ); + + // Clear the Lens request adapter when the chart is hidden + useEffect(() => { + if (chartHidden || !chart) { + inspectorAdapters.lensRequests = undefined; + } + }, [chart, chartHidden, inspectorAdapters]); + + // state.chartHidden is updated before searchSessionId, which can trigger duplicate + // requests, so instead of using state.chartHidden directly, we update chartHidden + // when searchSessionId changes + useEffect(() => { + setChartHidden(state.hideChart); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchSessionId]); + + /** + * Breakdown + */ + + const onBreakdownFieldChange = useCallback( + (breakdownField: DataViewField | undefined) => { + stateContainer.setAppState({ breakdownField: breakdownField?.name }); + }, + [stateContainer] + ); + + const field = useMemo( + () => (state.breakdownField ? dataView.getFieldByName(state.breakdownField) : undefined), + [dataView, state.breakdownField] + ); + + const breakdown = useMemo( + () => (isPlainRecord || !isTimeBased ? undefined : { field }), + [field, isPlainRecord, isTimeBased] ); - return { - topPanelHeight, - hits, - chart, - onEditVisualization: canVisualize ? onEditVisualization : undefined, - onTopPanelHeightChange, - onChartHiddenChange, - onTimeIntervalChange, - }; + // Don't render the unified histogram layout until the first search has been requested + return searchSessionId + ? { + topPanelHeight, + request, + hits, + chart, + breakdown, + onEditVisualization: canVisualize ? onEditVisualization : undefined, + onTopPanelHeightChange, + onChartHiddenChange, + onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, + } + : undefined; }; diff --git a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss deleted file mode 100644 index a58897e43b615..0000000000000 --- a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss +++ /dev/null @@ -1,4 +0,0 @@ -.dscLoading { - text-align: center; - padding: $euiSizeL 0; -} diff --git a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx index 949880d6c27d0..1879b5267bbf5 100644 --- a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx +++ b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx @@ -6,15 +6,32 @@ * Side Public License, v 1. */ -import './loading_spinner.scss'; - import React from 'react'; -import { EuiLoadingSpinner, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { + EuiLoadingSpinner, + EuiTitle, + EuiSpacer, + useEuiPaddingSize, + useEuiBackgroundColor, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { css } from '@emotion/react'; export function LoadingSpinner() { + const loadingSpinnerCss = css` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + padding: ${useEuiPaddingSize('l')} 0; + background-color: ${useEuiBackgroundColor('plain')}; + z-index: 3; + `; + return ( -
+

diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index 8ae4bbea6e269..06fe8031829f9 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -64,6 +64,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { stateContainer, adHocDataViewList, savedDataViewList, + searchSessionManager, } = useDiscoverState({ services, history: usedHistory, @@ -125,6 +126,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { updateDataViewList={updateDataViewList} adHocDataViewList={adHocDataViewList} savedDataViewList={savedDataViewList} + searchSessionManager={searchSessionManager} /> ); diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 8d40b20fbc9cd..df61c909c6a8e 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -194,10 +194,12 @@ export function useDiscoverState({ */ useEffect(() => { const unsubscribe = appStateContainer.subscribe(async (nextState) => { - const { hideChart, interval, sort, index } = state; - // chart was hidden, now it should be displayed, so data is needed - const chartDisplayChanged = nextState.hideChart !== hideChart && hideChart; + const { hideChart, interval, breakdownField, sort, index } = state; + // Cast to boolean to avoid false positives when comparing + // undefined and false, which would trigger a refetch + const chartDisplayChanged = Boolean(nextState.hideChart) !== Boolean(hideChart); const chartIntervalChanged = nextState.interval !== interval; + const breakdownFieldChanged = nextState.breakdownField !== breakdownField; const docTableSortChanged = !isEqual(nextState.sort, sort); const dataViewChanged = !isEqual(nextState.index, index); // NOTE: this is also called when navigating from discover app to context app @@ -230,9 +232,15 @@ export function useDiscoverState({ reset(); } - if (chartDisplayChanged || chartIntervalChanged || docTableSortChanged) { + if ( + chartDisplayChanged || + chartIntervalChanged || + breakdownFieldChanged || + docTableSortChanged + ) { refetch$.next(undefined); } + setState(nextState); }); return () => unsubscribe(); @@ -326,5 +334,6 @@ export function useDiscoverState({ persistDataView, updateAdHocDataViewId, updateDataViewList, + searchSessionManager, }; } diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts index 66c5542f5647a..60327e84f2cd8 100644 --- a/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts @@ -10,15 +10,23 @@ import { renderHook } from '@testing-library/react-hooks'; import { discoverServiceMock } from '../../../__mocks__/services'; import { savedSearchMock } from '../../../__mocks__/saved_search'; import { useInspector } from './use_inspector'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { Adapters, RequestAdapter } from '@kbn/inspector-plugin/common'; +import { OverlayRef } from '@kbn/core/public'; +import { AggregateRequestAdapter } from '../utils/aggregate_request_adapter'; describe('test useInspector', () => { test('inspector open function is executed, expanded doc is closed', async () => { const setExpandedDoc = jest.fn(); - + let adapters: Adapters | undefined; + jest.spyOn(discoverServiceMock.inspector, 'open').mockImplementation((localAdapters) => { + adapters = localAdapters; + return {} as OverlayRef; + }); + const requests = new RequestAdapter(); + const lensRequests = new RequestAdapter(); const { result } = renderHook(() => { return useInspector({ - inspectorAdapters: { requests: new RequestAdapter() }, + inspectorAdapters: { requests, lensRequests }, savedSearch: savedSearchMock, inspector: discoverServiceMock.inspector, setExpandedDoc, @@ -27,5 +35,10 @@ describe('test useInspector', () => { result.current(); expect(setExpandedDoc).toHaveBeenCalledWith(undefined); expect(discoverServiceMock.inspector.open).toHaveBeenCalled(); + expect(adapters?.requests).toBeInstanceOf(AggregateRequestAdapter); + expect(adapters?.requests?.getRequests()).toEqual([ + ...requests.getRequests(), + ...lensRequests.getRequests(), + ]); }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.ts index c7bcc0ba1cb4b..e23ca6425aa71 100644 --- a/src/plugins/discover/public/application/main/hooks/use_inspector.ts +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.ts @@ -14,6 +14,12 @@ import { } from '@kbn/inspector-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../types'; +import { AggregateRequestAdapter } from '../utils/aggregate_request_adapter'; + +export interface InspectorAdapters { + requests: RequestAdapter; + lensRequests?: RequestAdapter; +} export function useInspector({ setExpandedDoc, @@ -21,7 +27,7 @@ export function useInspector({ inspectorAdapters, savedSearch, }: { - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; savedSearch: SavedSearch; setExpandedDoc: (doc?: DataTableRecord) => void; inspector: InspectorPublicPluginStart; @@ -31,11 +37,24 @@ export function useInspector({ const onOpenInspector = useCallback(() => { // prevent overlapping setExpandedDoc(undefined); - const session = inspector.open(inspectorAdapters, { - title: savedSearch.title, - }); + + const requestAdapters = inspectorAdapters.lensRequests + ? [inspectorAdapters.requests, inspectorAdapters.lensRequests] + : [inspectorAdapters.requests]; + + const session = inspector.open( + { requests: new AggregateRequestAdapter(requestAdapters) }, + { title: savedSearch.title } + ); + setInspectorSession(session); - }, [setExpandedDoc, inspectorAdapters, savedSearch, inspector]); + }, [ + setExpandedDoc, + inspectorAdapters.lensRequests, + inspectorAdapters.requests, + inspector, + savedSearch.title, + ]); useEffect(() => { return () => { diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts index 34cdeb232be88..f46378053d355 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts @@ -45,7 +45,6 @@ describe('test useSavedSearch', () => { expect(result.current.data$.main$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(result.current.data$.documents$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(result.current.data$.totalHits$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - expect(result.current.data$.charts$.getValue().fetchStatus).toBe(FetchStatus.LOADING); }); test('refetch$ triggers a search', async () => { const { history, searchSessionManager } = createSearchSessionMock(); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts index 2f097daac982d..4f48945daaad1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts @@ -25,19 +25,18 @@ import { useBehaviorSubject } from './use_behavior_subject'; import { sendResetMsg } from './use_saved_search_messages'; import { getFetch$ } from '../utils/get_fetch_observable'; import type { DataTableRecord } from '../../../types'; +import type { InspectorAdapters } from './use_inspector'; export interface SavedSearchData { main$: DataMain$; documents$: DataDocuments$; totalHits$: DataTotalHits$; - charts$: DataCharts$; availableFields$: AvailableFields$; } export type DataMain$ = BehaviorSubject; export type DataDocuments$ = BehaviorSubject; export type DataTotalHits$ = BehaviorSubject; -export type DataCharts$ = BehaviorSubject; export type AvailableFields$ = BehaviorSubject; export type DataRefetch$ = Subject; @@ -46,7 +45,7 @@ export interface UseSavedSearch { refetch$: DataRefetch$; data$: SavedSearchData; reset: () => void; - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; } export enum RecordRawType { @@ -78,8 +77,6 @@ export interface DataDocumentsMsg extends DataMsg { } export interface DataTotalHitsMsg extends DataMsg { - fetchStatus: FetchStatus; - error?: Error; result?: number; } @@ -128,7 +125,6 @@ export const useSavedSearch = ({ const main$: DataMain$ = useBehaviorSubject(initialState) as DataMain$; const documents$: DataDocuments$ = useBehaviorSubject(initialState) as DataDocuments$; const totalHits$: DataTotalHits$ = useBehaviorSubject(initialState) as DataTotalHits$; - const charts$: DataCharts$ = useBehaviorSubject(initialState) as DataCharts$; const availableFields$: AvailableFields$ = useBehaviorSubject(initialState) as AvailableFields$; const dataSubjects = useMemo(() => { @@ -136,10 +132,9 @@ export const useSavedSearch = ({ main$, documents$, totalHits$, - charts$, availableFields$, }; - }, [main$, charts$, documents$, totalHits$, availableFields$]); + }, [main$, documents$, totalHits$, availableFields$]); /** * The observable to trigger data fetching in UI diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts index 1159aee1c5d13..5973d679b6b1c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts @@ -6,8 +6,10 @@ * Side Public License, v 1. */ import { + checkHitCount, sendCompleteMsg, sendErrorMsg, + sendErrorTo, sendLoadingMsg, sendNoResultsFoundMsg, sendPartialMsg, @@ -16,6 +18,7 @@ import { FetchStatus } from '../../types'; import { BehaviorSubject } from 'rxjs'; import { DataMainMsg, RecordRawType } from './use_saved_search'; import { filter } from 'rxjs/operators'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; describe('test useSavedSearch message generators', () => { test('sendCompleteMsg', (done) => { @@ -62,7 +65,10 @@ describe('test useSavedSearch message generators', () => { done(); } }); - sendLoadingMsg(main$, RecordRawType.DOCUMENT); + sendLoadingMsg(main$, { + foundDocuments: true, + recordRawType: RecordRawType.DOCUMENT, + }); }); test('sendErrorMsg', (done) => { const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.PARTIAL }); @@ -92,4 +98,36 @@ describe('test useSavedSearch message generators', () => { }); sendCompleteMsg(main$, false); }); + + test('sendErrorTo', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.PARTIAL }); + const data = dataPluginMock.createStartContract(); + const error = new Error('Pls help!'); + main$.subscribe((value) => { + expect(data.search.showError).toBeCalledWith(error); + expect(value.fetchStatus).toBe(FetchStatus.ERROR); + expect(value.error).toBe(error); + done(); + }); + sendErrorTo(data, main$)(error); + }); + + test('checkHitCount with hits', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.LOADING }); + main$.subscribe((value) => { + expect(value.fetchStatus).toBe(FetchStatus.PARTIAL); + done(); + }); + checkHitCount(main$, 100); + }); + + test('checkHitCount without hits', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.LOADING }); + main$.subscribe((value) => { + expect(value.fetchStatus).toBe(FetchStatus.COMPLETE); + expect(value.foundDocuments).toBe(false); + done(); + }); + checkHitCount(main$, 0); + }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts index ae5abb36378a8..ab121f76e15a0 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { AggregateQuery, Query } from '@kbn/es-query'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../types'; -import { - DataCharts$, +import type { DataDocuments$, DataMain$, + DataMsg, DataTotalHits$, - RecordRawType, SavedSearchData, } from './use_saved_search'; @@ -60,27 +60,22 @@ export function sendPartialMsg(main$: DataMain$) { /** * Send LOADING message via main observable */ -export function sendLoadingMsg( - data$: DataMain$ | DataDocuments$ | DataTotalHits$ | DataCharts$, - recordRawType: RecordRawType, - query?: AggregateQuery | Query +export function sendLoadingMsg( + data$: BehaviorSubject, + props: Omit ) { if (data$.getValue().fetchStatus !== FetchStatus.LOADING) { data$.next({ + ...props, fetchStatus: FetchStatus.LOADING, - recordRawType, - query, - }); + } as T); } } /** * Send ERROR message */ -export function sendErrorMsg( - data$: DataMain$ | DataDocuments$ | DataTotalHits$ | DataCharts$, - error: Error -) { +export function sendErrorMsg(data$: DataMain$ | DataDocuments$ | DataTotalHits$, error: Error) { const recordRawType = data$.getValue().recordRawType; data$.next({ fetchStatus: FetchStatus.ERROR, @@ -105,14 +100,43 @@ export function sendResetMsg(data: SavedSearchData, initialFetchStatus: FetchSta result: [], recordRawType, }); - data.charts$.next({ - fetchStatus: initialFetchStatus, - response: undefined, - recordRawType, - }); data.totalHits$.next({ fetchStatus: initialFetchStatus, result: undefined, recordRawType, }); } + +/** + * Method to create an error handler that will forward the received error + * to the specified subjects. It will ignore AbortErrors and will use the data + * plugin to show a toast for the error (e.g. allowing better insights into shard failures). + */ +export const sendErrorTo = ( + data: DataPublicPluginStart, + ...errorSubjects: Array +) => { + return (error: Error) => { + if (error instanceof Error && error.name === 'AbortError') { + return; + } + + data.search.showError(error); + errorSubjects.forEach((subject) => sendErrorMsg(subject, error)); + }; +}; + +/** + * This method checks the passed in hit count and will send a PARTIAL message to main$ + * if there are results, indicating that we have finished some of the requests that have been + * sent. If there are no results we already COMPLETE main$ with no results found, so Discover + * can show the "no results" screen. We know at that point, that the other query returning + * will neither carry any data, since there are no documents. + */ +export const checkHitCount = (main$: DataMain$, hitsCount: number) => { + if (hitsCount > 0) { + sendPartialMsg(main$); + } else { + sendNoResultsFoundMsg(main$); + } +}; diff --git a/src/plugins/discover/public/application/main/services/discover_search_session.ts b/src/plugins/discover/public/application/main/services/discover_search_session.ts index 5797b0381b1bf..0cbaf74159a80 100644 --- a/src/plugins/discover/public/application/main/services/discover_search_session.ts +++ b/src/plugins/discover/public/application/main/services/discover_search_session.ts @@ -31,6 +31,8 @@ export class DiscoverSearchSessionManager { * skips if `searchSessionId` matches current search session id */ readonly newSearchSessionIdFromURL$: Rx.Observable; + readonly searchSessionId$: Rx.Observable; + private readonly deps: DiscoverSearchSessionManagerDeps; constructor(deps: DiscoverSearchSessionManagerDeps) { @@ -44,6 +46,7 @@ export class DiscoverSearchSessionManager { return !this.deps.session.isCurrentSession(searchSessionId); }) ); + this.searchSessionId$ = this.deps.session.getSession$(); } /** diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 611b59eacdc79..77e870dfc75a5 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -98,6 +98,10 @@ export interface AppState { * Number of rows in the grid per page */ rowsPerPage?: number; + /** + * Current histogram breakdown field name + */ + breakdownField?: string; } export interface AppStateUrl extends Omit { @@ -447,5 +451,6 @@ function createUrlGeneratorState({ useHash: false, viewMode: appState.viewMode, hideAggregatedPreview: appState.hideAggregatedPreview, + breakdownField: appState.breakdownField, }; } diff --git a/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts new file mode 100644 index 0000000000000..effbb192e863b --- /dev/null +++ b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts @@ -0,0 +1,42 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { AggregateRequestAdapter } from './aggregate_request_adapter'; + +describe('AggregateRequestAdapter', () => { + it('should return all requests from all adapters', () => { + const adapter1 = new RequestAdapter(); + const adapter2 = new RequestAdapter(); + const adapter3 = new RequestAdapter(); + const aggregateAdapter = new AggregateRequestAdapter([adapter1, adapter2, adapter3]); + adapter1.start('request1'); + adapter2.start('request2'); + adapter3.start('request3'); + expect(aggregateAdapter.getRequests().map((request) => request.name)).toEqual([ + 'request1', + 'request2', + 'request3', + ]); + }); + + it('should allow adding and removing change listeners for all adapters', () => { + const adapter1 = new RequestAdapter(); + const adapter2 = new RequestAdapter(); + const aggregateAdapter = new AggregateRequestAdapter([adapter1, adapter2]); + const listener = jest.fn(); + aggregateAdapter.addListener('change', listener); + adapter1.start('request1'); + adapter2.start('request2'); + expect(listener).toHaveBeenCalledTimes(2); + aggregateAdapter.removeListener('change', listener); + adapter1.start('request3'); + adapter2.start('request4'); + expect(listener).toHaveBeenCalledTimes(2); + }); +}); diff --git a/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts new file mode 100644 index 0000000000000..4ce55c0723a11 --- /dev/null +++ b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts @@ -0,0 +1,132 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { RequestAdapter, Request } from '@kbn/inspector-plugin/public'; + +/** + * A request adapter that aggregates multiple separate adapters into one to allow inspection + */ +export class AggregateRequestAdapter extends RequestAdapter { + private readonly adapters: RequestAdapter[]; + + constructor(adapters: RequestAdapter[]) { + super(); + this.adapters = adapters; + } + + public reset(...args: Parameters): void { + super.reset(...args); + this.adapters.forEach((adapter) => adapter.reset(...args)); + } + + public resetRequest(...args: Parameters): void { + super.resetRequest(...args); + this.adapters.forEach((adapter) => adapter.resetRequest(...args)); + } + + public getRequests(...args: Parameters): Request[] { + return [ + ...super.getRequests(), + ...this.adapters.map((adapter) => adapter.getRequests(...args)).flat(), + ]; + } + + public addListener(...args: Parameters): this { + super.addListener(...args); + this.adapters.forEach((adapter) => adapter.addListener(...args)); + return this; + } + + public on(...args: Parameters): this { + super.on(...args); + this.adapters.forEach((adapter) => adapter.on(...args)); + return this; + } + + public once(...args: Parameters): this { + super.once(...args); + this.adapters.forEach((adapter) => adapter.once(...args)); + return this; + } + + public removeListener(...args: Parameters): this { + super.removeListener(...args); + this.adapters.forEach((adapter) => adapter.removeListener(...args)); + return this; + } + + public off(...args: Parameters): this { + super.off(...args); + this.adapters.forEach((adapter) => adapter.off(...args)); + return this; + } + + public removeAllListeners(...args: Parameters): this { + super.removeAllListeners(...args); + this.adapters.forEach((adapter) => adapter.removeAllListeners(...args)); + return this; + } + + public setMaxListeners(...args: Parameters): this { + super.setMaxListeners(...args); + this.adapters.forEach((adapter) => adapter.setMaxListeners(...args)); + return this; + } + + public getMaxListeners(...args: Parameters): number { + return Math.min( + super.getMaxListeners(...args), + ...this.adapters.map((adapter) => adapter.getMaxListeners(...args)) + ); + } + + public listeners(...args: Parameters): Function[] { + return [ + ...super.listeners(...args), + ...this.adapters.map((adapter) => adapter.listeners(...args)).flat(), + ]; + } + + public rawListeners(...args: Parameters): Function[] { + return [ + ...super.rawListeners(...args), + ...this.adapters.map((adapter) => adapter.rawListeners(...args)).flat(), + ]; + } + + public emit(...args: Parameters): boolean { + return [super.emit(...args), ...this.adapters.map((adapter) => adapter.emit(...args))].every( + (result) => result + ); + } + + public listenerCount(...args: Parameters): number { + return this.adapters + .map((adapter) => adapter.listenerCount(...args)) + .reduce((a, b) => a + b, super.listenerCount(...args)); + } + + public prependListener(...args: Parameters): this { + super.prependListener(...args); + this.adapters.forEach((adapter) => adapter.prependListener(...args)); + return this; + } + + public prependOnceListener(...args: Parameters): this { + super.prependOnceListener(...args); + this.adapters.forEach((adapter) => adapter.prependOnceListener(...args)); + return this; + } + + public eventNames(...args: Parameters): Array { + return [ + ...super.eventNames(...args), + ...this.adapters.map((adapter) => adapter.eventNames(...args)).flat(), + ]; + } +} diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 59dbc3ffe73d8..5258de6bdfdad 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -17,20 +17,17 @@ import { discoverServiceMock } from '../../../__mocks__/services'; import { fetchAll } from './fetch_all'; import { DataAvailableFieldsMsg, - DataChartsMessage, DataDocumentsMsg, DataMainMsg, DataTotalHitsMsg, + RecordRawType, SavedSearchData, } from '../hooks/use_saved_search'; import { fetchDocuments } from './fetch_documents'; import { fetchSql } from './fetch_sql'; -import { fetchChart } from './fetch_chart'; -import { fetchTotalHits } from './fetch_total_hits'; import { buildDataTableRecord } from '../../../utils/build_data_record'; import { dataViewMock } from '../../../__mocks__/data_view'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; jest.mock('./fetch_documents', () => ({ fetchDocuments: jest.fn().mockResolvedValue([]), @@ -40,17 +37,7 @@ jest.mock('./fetch_sql', () => ({ fetchSql: jest.fn().mockResolvedValue([]), })); -jest.mock('./fetch_chart', () => ({ - fetchChart: jest.fn(), -})); - -jest.mock('./fetch_total_hits', () => ({ - fetchTotalHits: jest.fn(), -})); - const mockFetchDocuments = fetchDocuments as unknown as jest.MockedFunction; -const mockFetchTotalHits = fetchTotalHits as unknown as jest.MockedFunction; -const mockFetchChart = fetchChart as unknown as jest.MockedFunction; const mockFetchSQL = fetchSql as unknown as jest.MockedFunction; function subjectCollector(subject: Subject): () => Promise { @@ -64,6 +51,8 @@ function subjectCollector(subject: Subject): () => Promise { }; } +const waitForNextTick = () => new Promise((resolve) => setTimeout(resolve, 0)); + describe('test fetchAll', () => { let subjects: SavedSearchData; let deps: Parameters[3]; @@ -73,7 +62,6 @@ describe('test fetchAll', () => { main$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), documents$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), totalHits$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), - charts$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), availableFields$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED, }), @@ -97,10 +85,6 @@ describe('test fetchAll', () => { mockFetchDocuments.mockReset().mockResolvedValue([]); mockFetchSQL.mockReset().mockResolvedValue([]); - mockFetchTotalHits.mockReset().mockResolvedValue(42); - mockFetchChart - .mockReset() - .mockResolvedValue({ totalHits: 42, response: {} as unknown as SearchResponse }); }); test('changes of fetchStatus when starting with FetchStatus.UNINITIALIZED', async () => { @@ -108,7 +92,8 @@ describe('test fetchAll', () => { subjects.main$.subscribe((value) => stateArr.push(value.fetchStatus)); - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); expect(stateArr).toEqual([ FetchStatus.UNINITIALIZED, @@ -125,7 +110,8 @@ describe('test fetchAll', () => { ]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -147,8 +133,18 @@ describe('test fetchAll', () => { const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - mockFetchTotalHits.mockResolvedValue(42); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 42, + }); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -157,44 +153,48 @@ describe('test fetchAll', () => { ]); }); - test('emits loading and response on charts$ correctly', async () => { - const collect = subjectCollector(subjects.charts$); - searchSource.getField('index')!.isTimeBased = () => true; - await fetchAll(subjects, searchSource, false, deps); - expect(await collect()).toEqual([ - { fetchStatus: FetchStatus.UNINITIALIZED }, - { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, - { - fetchStatus: FetchStatus.COMPLETE, - recordRawType: 'document', - response: {}, - }, - ]); - }); - test('should use charts query to fetch total hit count when chart is visible', async () => { const collect = subjectCollector(subjects.totalHits$); searchSource.getField('index')!.isTimeBased = () => true; - mockFetchChart.mockResolvedValue({ totalHits: 32, response: {} as unknown as SearchResponse }); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 32, + }); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, { fetchStatus: FetchStatus.PARTIAL, recordRawType: 'document', result: 0 }, // From documents query { fetchStatus: FetchStatus.COMPLETE, recordRawType: 'document', result: 32 }, ]); - expect(mockFetchTotalHits).not.toHaveBeenCalled(); }); test('should only fail totalHits$ query not main$ for error from that query', async () => { const collectTotalHits = subjectCollector(subjects.totalHits$); const collectMain = subjectCollector(subjects.main$); searchSource.getField('index')!.isTimeBased = () => false; - mockFetchTotalHits.mockRejectedValue({ msg: 'Oh noes!' }); const hits = [{ _id: '1', _index: 'logs' }]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.ERROR, + recordRawType: RecordRawType.DOCUMENT, + error: { msg: 'Oh noes!' } as unknown as Error, + }); + expect(await collectTotalHits()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -218,11 +218,21 @@ describe('test fetchAll', () => { const collectMain = subjectCollector(subjects.main$); searchSource.getField('index')!.isTimeBased = () => false; mockFetchDocuments.mockRejectedValue({ msg: 'This query failed' }); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 5, + }); + expect(await collectMain()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, - { fetchStatus: FetchStatus.PARTIAL, recordRawType: 'document' }, // From totalHits query { fetchStatus: FetchStatus.ERROR, error: { msg: 'This query failed' }, @@ -256,7 +266,9 @@ describe('test fetchAll', () => { savedSearch: savedSearchMock, services: discoverServiceMock, }; - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'plain', query }, diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index d530da1492fac..d782442db3953 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -8,31 +8,22 @@ import { DataPublicPluginStart, ISearchSource } from '@kbn/data-plugin/public'; import { Adapters } from '@kbn/inspector-plugin/common'; import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { DataViewType } from '@kbn/data-views-plugin/public'; import type { SavedSearch, SortOrder } from '@kbn/saved-search-plugin/public'; +import { BehaviorSubject, filter, firstValueFrom, map, merge, scan } from 'rxjs'; import { getRawRecordType } from './get_raw_record_type'; import { + checkHitCount, sendCompleteMsg, sendErrorMsg, + sendErrorTo, sendLoadingMsg, - sendNoResultsFoundMsg, - sendPartialMsg, sendResetMsg, } from '../hooks/use_saved_search_messages'; import { updateSearchSource } from './update_search_source'; import { fetchDocuments } from './fetch_documents'; -import { fetchTotalHits } from './fetch_total_hits'; -import { fetchChart } from './fetch_chart'; import { AppState } from '../services/discover_state'; import { FetchStatus } from '../../types'; -import { - DataCharts$, - DataDocuments$, - DataMain$, - DataTotalHits$, - RecordRawType, - SavedSearchData, -} from '../hooks/use_saved_search'; +import { DataMsg, RecordRawType, SavedSearchData } from '../hooks/use_saved_search'; import { DiscoverServices } from '../../../build_services'; import { fetchSql } from './fetch_sql'; @@ -50,8 +41,7 @@ export interface FetchDeps { /** * This function starts fetching all required queries in Discover. This will be the query to load the individual - * documents, and depending on whether a chart is shown either the aggregation query to load the chart data - * or a query to retrieve just the total hits. + * documents as well as any other requests that might be required to load the main view. * * This method returns a promise, which will resolve (without a value), as soon as all queries that have been started * have been completed (failed or successfully). @@ -64,30 +54,12 @@ export function fetchAll( ): Promise { const { initialFetchStatus, appStateContainer, services, useNewFieldsApi, data } = fetchDeps; - /** - * Method to create an error handler that will forward the received error - * to the specified subjects. It will ignore AbortErrors and will use the data - * plugin to show a toast for the error (e.g. allowing better insights into shard failures). - */ - const sendErrorTo = ( - ...errorSubjects: Array - ) => { - return (error: Error) => { - if (error instanceof Error && error.name === 'AbortError') { - return; - } - - data.search.showError(error); - errorSubjects.forEach((subject) => sendErrorMsg(subject, error)); - }; - }; - try { const dataView = searchSource.getField('index')!; if (reset) { sendResetMsg(dataSubjects, initialFetchStatus); } - const { hideChart, sort, query } = appStateContainer.getState(); + const { sort, query } = appStateContainer.getState(); const recordRawType = getRawRecordType(query); const useSql = recordRawType === RecordRawType.PLAIN; @@ -102,40 +74,17 @@ export function fetchAll( } // Mark all subjects as loading - sendLoadingMsg(dataSubjects.main$, recordRawType); - sendLoadingMsg(dataSubjects.documents$, recordRawType, query); - sendLoadingMsg(dataSubjects.totalHits$, recordRawType); - sendLoadingMsg(dataSubjects.charts$, recordRawType); - - const isChartVisible = - !hideChart && dataView.isTimeBased() && dataView.type !== DataViewType.ROLLUP; + sendLoadingMsg(dataSubjects.main$, { recordRawType }); + sendLoadingMsg(dataSubjects.documents$, { recordRawType, query }); + sendLoadingMsg(dataSubjects.totalHits$, { recordRawType }); // Start fetching all required requests const documents = useSql && query ? fetchSql(query, services.dataViews, data, services.expressions) : fetchDocuments(searchSource.createCopy(), fetchDeps); - const charts = - isChartVisible && !useSql ? fetchChart(searchSource.createCopy(), fetchDeps) : undefined; - const totalHits = - !isChartVisible && !useSql ? fetchTotalHits(searchSource.createCopy(), fetchDeps) : undefined; - /** - * This method checks the passed in hit count and will send a PARTIAL message to main$ - * if there are results, indicating that we have finished some of the requests that have been - * sent. If there are no results we already COMPLETE main$ with no results found, so Discover - * can show the "no results" screen. We know at that point, that the other query returning - * will neither carry any data, since there are no documents. - */ - const checkHitCount = (hitsCount: number) => { - if (hitsCount > 0) { - sendPartialMsg(dataSubjects.main$); - } else { - sendNoResultsFoundMsg(dataSubjects.main$); - } - }; // Handle results of the individual queries and forward the results to the corresponding dataSubjects - documents .then((docs) => { // If the total hits (or chart) query is still loading, emit a partial @@ -155,44 +104,20 @@ export function fetchAll( query, }); - checkHitCount(docs.length); + checkHitCount(dataSubjects.main$, docs.length); }) // Only the document query should send its errors to main$, to cause the full Discover app // to get into an error state. The other queries will not cause all of Discover to error out // but their errors will be shown in-place (e.g. of the chart). - .catch(sendErrorTo(dataSubjects.documents$, dataSubjects.main$)); - - charts - ?.then((chart) => { - dataSubjects.totalHits$.next({ - fetchStatus: FetchStatus.COMPLETE, - result: chart.totalHits, - recordRawType, - }); - - dataSubjects.charts$.next({ - fetchStatus: FetchStatus.COMPLETE, - response: chart.response, - recordRawType, - }); - - checkHitCount(chart.totalHits); - }) - .catch(sendErrorTo(dataSubjects.charts$, dataSubjects.totalHits$)); - - totalHits - ?.then((hitCount) => { - dataSubjects.totalHits$.next({ - fetchStatus: FetchStatus.COMPLETE, - result: hitCount, - recordRawType, - }); - checkHitCount(hitCount); - }) - .catch(sendErrorTo(dataSubjects.totalHits$)); + .catch(sendErrorTo(data, dataSubjects.documents$, dataSubjects.main$)); // Return a promise that will resolve once all the requests have finished or failed - return Promise.allSettled([documents, charts, totalHits]).then(() => { + return firstValueFrom( + merge( + fetchStatusByType(dataSubjects.documents$, 'documents'), + fetchStatusByType(dataSubjects.totalHits$, 'totalHits') + ).pipe(scan(toRequestFinishedMap, {}), filter(allRequestsFinished)) + ).then(() => { // Send a complete message to main$ once all queries are done and if main$ // is not already in an ERROR state, e.g. because the document query has failed. // This will only complete main$, if it hasn't already been completed previously @@ -207,3 +132,17 @@ export function fetchAll( return Promise.resolve(); } } + +const fetchStatusByType = (subject: BehaviorSubject, type: string) => + subject.pipe(map(({ fetchStatus }) => ({ type, fetchStatus }))); + +const toRequestFinishedMap = ( + currentMap: Record, + { type, fetchStatus }: { type: string; fetchStatus: FetchStatus } +) => ({ + ...currentMap, + [type]: [FetchStatus.COMPLETE, FetchStatus.ERROR].includes(fetchStatus), +}); + +const allRequestsFinished = (requests: Record) => + Object.values(requests).every((finished) => finished); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts deleted file mode 100644 index af2090347124d..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { of, throwError as throwErrorRx } from 'rxjs'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; -import { fetchChart, updateSearchSource } from './fetch_chart'; -import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { AppState } from '../services/discover_state'; -import { discoverServiceMock } from '../../../__mocks__/services'; -import { calculateBounds } from '@kbn/data-plugin/public'; -import { FetchDeps } from './fetch_all'; - -function getDeps() { - const deps = { - appStateContainer: { - getState: () => { - return { interval: 'auto' }; - }, - } as ReduxLikeStateContainer, - abortController: new AbortController(), - data: discoverServiceMock.data, - inspectorAdapters: { requests: new RequestAdapter() }, - onResults: jest.fn(), - savedSearch: savedSearchMockWithTimeField, - searchSessionId: '123', - } as unknown as FetchDeps; - deps.data.query.timefilter.timefilter.getTime = () => { - return { from: '2021-07-07T00:05:13.590', to: '2021-07-07T11:20:13.590' }; - }; - - deps.data.query.timefilter.timefilter.calculateBounds = (timeRange) => calculateBounds(timeRange); - return deps; -} - -const requestResult = { - id: 'Fjk5bndxTHJWU2FldVRVQ0tYR0VqOFEcRWtWNDhOdG5SUzJYcFhONVVZVTBJQToxMDMwOQ==', - rawResponse: { - took: 2, - timed_out: false, - _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, - hits: { max_score: null, hits: [], total: 42 }, - aggregations: { - '2': { - buckets: [ - { - key_as_string: '2021-07-07T06:36:00.000+02:00', - key: 1625632560000, - doc_count: 1, - }, - ], - }, - }, - }, - isPartial: false, - isRunning: false, - total: 1, - loaded: 1, - isRestored: false, -}; - -describe('test fetchCharts', () => { - test('updateSearchSource helper function', () => { - const chartAggConfigs = updateSearchSource( - savedSearchMockWithTimeField.searchSource, - 'auto', - discoverServiceMock.data - ); - expect(chartAggConfigs.aggs).toMatchInlineSnapshot(` - Array [ - Object { - "enabled": true, - "id": "1", - "params": Object { - "emptyAsNull": false, - }, - "schema": "metric", - "type": "count", - }, - Object { - "enabled": true, - "id": "2", - "params": Object { - "drop_partials": false, - "extendToTimeRange": false, - "extended_bounds": Object {}, - "field": "timestamp", - "interval": "auto", - "min_doc_count": 1, - "scaleMetricValues": false, - "timeRange": Object { - "from": "now-15m", - "to": "now", - }, - "useNormalizedEsInterval": true, - "used_interval": "0ms", - }, - "schema": "segment", - "type": "date_histogram", - }, - ] - `); - }); - - test('resolves with summarized chart data', async () => { - savedSearchMockWithTimeField.searchSource.fetch$ = () => of(requestResult); - - const result = await fetchChart(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(result).toHaveProperty('totalHits', 42); - expect(result).toHaveProperty('response'); - }); - - test('rejects promise on query failure', async () => { - savedSearchMockWithTimeField.searchSource.fetch$ = () => - throwErrorRx(() => new Error('Oh noes!')); - - await expect(fetchChart(savedSearchMockWithTimeField.searchSource, getDeps())).rejects.toEqual( - new Error('Oh noes!') - ); - }); - - test('fetch$ is called with request specific execution context', async () => { - const fetch$Mock = jest.fn().mockReturnValue(of(requestResult)); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchChart(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch chart data and total hits", - } - `); - }); -}); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.ts deleted file mode 100644 index e4e5b67782cb9..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { filter, map } from 'rxjs/operators'; -import { lastValueFrom } from 'rxjs'; -import { DataPublicPluginStart, isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { getChartAggConfigs } from '@kbn/unified-histogram-plugin/public'; -import { FetchDeps } from './fetch_all'; - -interface Result { - totalHits: number; - response: SearchResponse; -} - -export function fetchChart( - searchSource: ISearchSource, - { abortController, appStateContainer, data, inspectorAdapters, searchSessionId }: FetchDeps -): Promise { - const timeInterval = appStateContainer.getState().interval ?? 'auto'; - - updateSearchSource(searchSource, timeInterval, data); - - const executionContext = { - description: 'fetch chart data and total hits', - }; - - const fetch$ = searchSource - .fetch$({ - abortSignal: abortController.signal, - sessionId: searchSessionId, - inspector: { - adapter: inspectorAdapters.requests, - title: i18n.translate('discover.inspectorRequestDataTitleChart', { - defaultMessage: 'Chart data', - }), - description: i18n.translate('discover.inspectorRequestDescriptionChart', { - defaultMessage: - 'This request queries Elasticsearch to fetch the aggregation data for the chart.', - }), - }, - executionContext, - }) - .pipe( - filter((res) => isCompleteResponse(res)), - map((res) => ({ - response: res.rawResponse, - totalHits: res.rawResponse.hits.total as number, - })) - ); - - return lastValueFrom(fetch$); -} - -export function updateSearchSource( - searchSource: ISearchSource, - timeInterval: string, - data: DataPublicPluginStart -) { - const dataView = searchSource.getField('index')!; - searchSource.setField('filter', data.query.timefilter.timefilter.createFilter(dataView)); - searchSource.setField('size', 0); - searchSource.setField('trackTotalHits', true); - const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); - searchSource.setField('aggs', chartAggConfigs.toDsl()); - searchSource.removeField('sort'); - searchSource.removeField('fields'); - return chartAggConfigs; -} diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts index 4809da54655be..28738cdc522c9 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts @@ -8,12 +8,11 @@ import { fetchDocuments } from './fetch_documents'; import { throwError as throwErrorRx, of } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; +import { savedSearchMock } from '../../../__mocks__/saved_search'; import { discoverServiceMock } from '../../../__mocks__/services'; import { IKibanaSearchResponse } from '@kbn/data-plugin/public'; import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { FetchDeps } from './fetch_all'; -import { fetchTotalHits } from './fetch_total_hits'; import type { EsHitRecord } from '../../../types'; import { buildDataTableRecord } from '../../../utils/build_data_record'; import { dataViewMock } from '../../../__mocks__/data_view'; @@ -47,21 +46,4 @@ describe('test fetchDocuments', () => { new Error('Oh noes!') ); }); - - test('fetch$ is called with execution context containing savedSearch id', async () => { - const fetch$Mock = jest.fn().mockReturnValue( - of({ - rawResponse: { hits: { hits: [] } }, - } as unknown as IKibanaSearchResponse) - ); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchTotalHits(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch total hits", - } - `); - }); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts deleted file mode 100644 index f2851a57e7365..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { throwError as throwErrorRx, of } from 'rxjs'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; -import { fetchTotalHits } from './fetch_total_hits'; -import { discoverServiceMock } from '../../../__mocks__/services'; -import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { IKibanaSearchResponse } from '@kbn/data-plugin/public'; -import { FetchDeps } from './fetch_all'; - -const getDeps = () => - ({ - abortController: new AbortController(), - inspectorAdapters: { requests: new RequestAdapter() }, - searchSessionId: '123', - data: discoverServiceMock.data, - savedSearch: savedSearchMock, - } as FetchDeps); - -describe('test fetchTotalHits', () => { - test('resolves returned promise with hit count', async () => { - savedSearchMock.searchSource.fetch$ = () => - of({ rawResponse: { hits: { total: 45 } } } as IKibanaSearchResponse>); - - await expect(fetchTotalHits(savedSearchMock.searchSource, getDeps())).resolves.toBe(45); - }); - - test('rejects in case of an error', async () => { - savedSearchMock.searchSource.fetch$ = () => throwErrorRx(() => new Error('Oh noes!')); - - await expect(fetchTotalHits(savedSearchMock.searchSource, getDeps())).rejects.toEqual( - new Error('Oh noes!') - ); - }); - test('fetch$ is called with execution context containing savedSearch id', async () => { - const fetch$Mock = jest - .fn() - .mockReturnValue( - of({ rawResponse: { hits: { total: 45 } } } as IKibanaSearchResponse) - ); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchTotalHits(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch total hits", - } - `); - }); -}); diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts deleted file mode 100644 index 16bd138e2caf5..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { filter, map } from 'rxjs/operators'; -import { lastValueFrom } from 'rxjs'; -import { isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; -import { DataViewType } from '@kbn/data-views-plugin/public'; -import { FetchDeps } from './fetch_all'; - -export function fetchTotalHits( - searchSource: ISearchSource, - { abortController, inspectorAdapters, searchSessionId, savedSearch }: FetchDeps -) { - searchSource.setField('trackTotalHits', true); - searchSource.setField('size', 0); - searchSource.removeField('sort'); - searchSource.removeField('fields'); - searchSource.removeField('aggs'); - if (searchSource.getField('index')?.type === DataViewType.ROLLUP) { - // We treat that data view as "normal" even if it was a rollup data view, - // since the rollup endpoint does not support querying individual documents, but we - // can get them from the regular _search API that will be used if the data view - // not a rollup data view. - searchSource.setOverwriteDataViewType(undefined); - } - - const executionContext = { - description: 'fetch total hits', - }; - - const fetch$ = searchSource - .fetch$({ - inspector: { - adapter: inspectorAdapters.requests, - title: i18n.translate('discover.inspectorRequestDataTitleTotalHits', { - defaultMessage: 'Total hits', - }), - description: i18n.translate('discover.inspectorRequestDescriptionTotalHits', { - defaultMessage: 'This request queries Elasticsearch to fetch the total hits.', - }), - }, - abortSignal: abortController.signal, - sessionId: searchSessionId, - executionContext, - }) - .pipe( - filter((res) => isCompleteResponse(res)), - map((res) => res.rawResponse.hits.total as number) - ); - - return lastValueFrom(fetch$); -} diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts index 1d5cf07446d60..aed900821c747 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts @@ -22,6 +22,7 @@ describe('getStateDefaults', () => { }); expect(actual).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "default_column", ], @@ -55,6 +56,7 @@ describe('getStateDefaults', () => { }); expect(actual).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "default_column", ], diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts index b8b3c3579f343..f32af6ec5f23b 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts @@ -70,6 +70,7 @@ export function getStateDefaults({ rowHeight: undefined, rowsPerPage: undefined, grid: undefined, + breakdownField: undefined, }; if (savedSearch.grid) { defaultState.grid = savedSearch.grid; @@ -90,5 +91,9 @@ export function getStateDefaults({ defaultState.rowsPerPage = savedSearch.rowsPerPage; } + if (savedSearch.breakdownField) { + defaultState.breakdownField = savedSearch.breakdownField; + } + return defaultState; } diff --git a/src/plugins/discover/public/application/main/utils/persist_saved_search.ts b/src/plugins/discover/public/application/main/utils/persist_saved_search.ts index 73859e46eaf24..8162f3650b8b0 100644 --- a/src/plugins/discover/public/application/main/utils/persist_saved_search.ts +++ b/src/plugins/discover/public/application/main/utils/persist_saved_search.ts @@ -56,6 +56,12 @@ export async function persistSavedSearch( savedSearch.viewMode = state.viewMode; } + if (typeof state.breakdownField !== 'undefined') { + savedSearch.breakdownField = state.breakdownField; + } else if (savedSearch.breakdownField) { + savedSearch.breakdownField = ''; + } + if (state.hideAggregatedPreview) { savedSearch.hideAggregatedPreview = state.hideAggregatedPreview; } diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 4c25f466b0fdd..27f5d59b07e10 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -46,6 +46,7 @@ import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-action import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; import { DiscoverAppLocator } from './locator'; import { getHistory } from './kibana_services'; import { DiscoverStartPlugins } from './plugin'; @@ -97,6 +98,7 @@ export interface DiscoverServices { savedObjectsManagement: SavedObjectsManagementPluginStart; savedObjectsTagging?: SavedObjectsTaggingApi; unifiedSearch: UnifiedSearchPublicPluginStart; + lens: LensPublicStart; } export const buildServices = memoize(function ( @@ -150,5 +152,6 @@ export const buildServices = memoize(function ( savedObjectsTagging: plugins.savedObjectsTaggingOss?.getTaggingApi(), savedObjectsManagement: plugins.savedObjectsManagement, unifiedSearch: plugins.unifiedSearch, + lens: plugins.lens, }; }); diff --git a/src/plugins/discover/public/locator.ts b/src/plugins/discover/public/locator.ts index e59c61c98412c..e803433c4d70c 100644 --- a/src/plugins/discover/public/locator.ts +++ b/src/plugins/discover/public/locator.ts @@ -91,6 +91,10 @@ export interface DiscoverAppLocatorParams extends SerializableRecord { * Hide mini distribution/preview charts when in Field Statistics mode */ hideAggregatedPreview?: boolean; + /** + * Breakdown field + */ + breakdownField?: string; } export type DiscoverAppLocator = LocatorPublic; @@ -129,6 +133,7 @@ export class DiscoverAppLocatorDefinition implements LocatorDefinition { expect(savedObjectsClient.resolve).toHaveBeenCalled(); expect(savedSearch).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "_source", ], @@ -198,6 +199,7 @@ describe('getSavedSearch', () => { expect(savedObjectsClient.resolve).toHaveBeenCalled(); expect(savedSearch).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "_source", ], diff --git a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts index 9f227bc1afd04..feabac408c116 100644 --- a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts +++ b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts @@ -41,6 +41,7 @@ describe('saved_searches_utils', () => { ) ).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "a", "b", @@ -128,6 +129,7 @@ describe('saved_searches_utils', () => { expect(toSavedSearchAttributes(savedSearch, '{}')).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "c", "d", diff --git a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts index 5d37355ea818d..83286f455d8c4 100644 --- a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts +++ b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts @@ -50,6 +50,7 @@ export const fromSavedSearchAttributes = ( timeRange: attributes.timeRange, refreshInterval: attributes.refreshInterval, rowsPerPage: attributes.rowsPerPage, + breakdownField: attributes.breakdownField, }); export const toSavedSearchAttributes = ( @@ -72,4 +73,5 @@ export const toSavedSearchAttributes = ( timeRange: savedSearch.timeRange, refreshInterval: savedSearch.refreshInterval, rowsPerPage: savedSearch.rowsPerPage, + breakdownField: savedSearch.breakdownField, }); diff --git a/src/plugins/saved_search/public/services/saved_searches/types.ts b/src/plugins/saved_search/public/services/saved_searches/types.ts index 81dbe19517798..f4e5ebecd559f 100644 --- a/src/plugins/saved_search/public/services/saved_searches/types.ts +++ b/src/plugins/saved_search/public/services/saved_searches/types.ts @@ -46,6 +46,7 @@ export interface SavedSearchAttributes { refreshInterval?: RefreshInterval; rowsPerPage?: number; + breakdownField?: string; } /** @internal **/ @@ -82,4 +83,5 @@ export interface SavedSearch { refreshInterval?: RefreshInterval; rowsPerPage?: number; + breakdownField?: string; } diff --git a/src/plugins/saved_search/server/saved_objects/search.ts b/src/plugins/saved_search/server/saved_objects/search.ts index 29130ac519334..5960cd8ebdbe9 100644 --- a/src/plugins/saved_search/server/saved_objects/search.ts +++ b/src/plugins/saved_search/server/saved_objects/search.ts @@ -68,6 +68,7 @@ export function getSavedSearchObjectType( }, }, rowsPerPage: { type: 'integer', index: false, doc_values: false }, + breakdownField: { type: 'text' }, }, }, migrations: () => getAllMigrations(getSearchSourceMigrations()), diff --git a/src/plugins/unified_histogram/kibana.json b/src/plugins/unified_histogram/kibana.json index f89f9c9d4c714..5be043637ed33 100755 --- a/src/plugins/unified_histogram/kibana.json +++ b/src/plugins/unified_histogram/kibana.json @@ -11,5 +11,5 @@ "ui": true, "requiredPlugins": [], "optionalPlugins": [], - "requiredBundles": ["charts", "data"] + "requiredBundles": ["data", "dataViews", "embeddable", "kibanaUtils", "inspector"] } diff --git a/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts index 158d697d67c71..b0ec2fcf84ebb 100644 --- a/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts +++ b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts @@ -12,12 +12,14 @@ import { buildDataViewMock } from './data_view'; const fields = [ { name: '_index', + displayName: '_index', type: 'string', scripted: false, filterable: true, }, { name: 'timestamp', + displayName: 'timestamp', type: 'date', scripted: false, filterable: true, @@ -26,12 +28,14 @@ const fields = [ }, { name: 'message', + displayName: 'message', type: 'string', scripted: false, filterable: false, }, { name: 'extension', + displayName: 'extension', type: 'string', scripted: false, filterable: true, @@ -39,6 +43,7 @@ const fields = [ }, { name: 'bytes', + displayName: 'bytes', type: 'number', scripted: false, filterable: true, @@ -46,6 +51,7 @@ const fields = [ }, { name: 'scripted', + displayName: 'scripted', type: 'number', scripted: true, filterable: false, diff --git a/src/plugins/unified_histogram/public/__mocks__/services.ts b/src/plugins/unified_histogram/public/__mocks__/services.ts index e827596d88feb..1ce16ad8fae85 100644 --- a/src/plugins/unified_histogram/public/__mocks__/services.ts +++ b/src/plugins/unified_histogram/public/__mocks__/services.ts @@ -25,4 +25,5 @@ export const unifiedHistogramServicesMock = { useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), }, + lens: { EmbeddableComponent: jest.fn(() => null) }, } as unknown as UnifiedHistogramServices; diff --git a/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx new file mode 100644 index 0000000000000..2b6b8bd7c537f --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx @@ -0,0 +1,73 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiComboBox } from '@elastic/eui'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import React from 'react'; +import { UnifiedHistogramBreakdownContext } from '..'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +describe('BreakdownFieldSelector', () => { + it('should pass fields that support breakdown as options to the EuiComboBox', () => { + const onBreakdownFieldChange = jest.fn(); + const breakdown: UnifiedHistogramBreakdownContext = { + field: undefined, + }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + expect(comboBox.prop('options')).toEqual( + dataViewWithTimefieldMock.fields + .filter(fieldSupportsBreakdown) + .map((field) => ({ label: field.displayName, value: field.name })) + .sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase())) + ); + }); + + it('should pass selectedOptions to the EuiComboBox if breakdown.field is defined', () => { + const onBreakdownFieldChange = jest.fn(); + const field = dataViewWithTimefieldMock.fields.find((f) => f.name === 'extension')!; + const breakdown: UnifiedHistogramBreakdownContext = { field }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + expect(comboBox.prop('selectedOptions')).toEqual([ + { label: field.displayName, value: field.name }, + ]); + }); + + it('should call onBreakdownFieldChange with the selected field when the user selects a field', () => { + const onBreakdownFieldChange = jest.fn(); + const breakdown: UnifiedHistogramBreakdownContext = { + field: undefined, + }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + const selectedField = dataViewWithTimefieldMock.fields.find((f) => f.name === 'extension')!; + comboBox.prop('onChange')!([{ label: selectedField.displayName, value: selectedField.name }]); + expect(onBreakdownFieldChange).toHaveBeenCalledWith(selectedField); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx new file mode 100644 index 0000000000000..ef2a14e4423b6 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx @@ -0,0 +1,89 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiComboBox, EuiComboBoxOptionOption, EuiToolTip, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; +import { i18n } from '@kbn/i18n'; +import React, { useCallback, useState } from 'react'; +import { UnifiedHistogramBreakdownContext } from '../types'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +export interface BreakdownFieldSelectorProps { + dataView: DataView; + breakdown: UnifiedHistogramBreakdownContext; + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; +} + +export const BreakdownFieldSelector = ({ + dataView, + breakdown, + onBreakdownFieldChange, +}: BreakdownFieldSelectorProps) => { + const fieldOptions = dataView.fields + .filter(fieldSupportsBreakdown) + .map((field) => ({ label: field.displayName, value: field.name })) + .sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase())); + + const selectedFields = breakdown.field + ? [{ label: breakdown.field.displayName, value: breakdown.field.name }] + : []; + + const onFieldChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]) => { + const field = newOptions.length + ? dataView.fields.find((currentField) => currentField.name === newOptions[0].value) + : undefined; + + onBreakdownFieldChange?.(field); + }, + [dataView.fields, onBreakdownFieldChange] + ); + + const [fieldPopoverDisabled, setFieldPopoverDisabled] = useState(false); + const disableFieldPopover = useCallback(() => setFieldPopoverDisabled(true), []); + const enableFieldPopover = useCallback( + () => setTimeout(() => setFieldPopoverDisabled(false)), + [] + ); + + const { euiTheme } = useEuiTheme(); + const breakdownCss = css` + width: 100%; + max-width: ${euiTheme.base * 22}px; + `; + + return ( + + + + ); +}; diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts b/src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts similarity index 69% rename from src/plugins/unified_histogram/public/chart/build_chart_data.test.ts rename to src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts index 6c920a4a1a5ab..072f7a811babe 100644 --- a/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts +++ b/src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts @@ -9,9 +9,9 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { calculateBounds } from '@kbn/data-plugin/public'; -import { buildChartData } from './build_chart_data'; +import { buildBucketInterval } from './build_bucket_interval'; -describe('buildChartData', () => { +describe('buildBucketInterval', () => { const getOptions = () => { const response = { took: 0, @@ -72,54 +72,29 @@ describe('buildChartData', () => { dataView, timeInterval: 'auto', response, + timeRange: { + from: '1991-03-29T08:04:00.694Z', + to: '2021-03-29T07:04:00.695Z', + }, }; }; - const expectedChartData = { - xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], - xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, - xAxisLabel: 'timestamp per 0 milliseconds', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: 'P0D', - intervalESUnit: 'ms', - intervalESValue: 0, - min: '1991-03-29T08:04:00.694Z', - max: '2021-03-29T07:04:00.695Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1664996400000, y: 6 }, - { x: 1664998200000, y: 2 }, - { x: 1665000000000, y: 3 }, - { x: 1665001800000, y: 8 }, - { x: 1665003600000, y: 10 }, - ], - }; - - it('should return the correct data', () => { - const { bucketInterval, chartData } = buildChartData(getOptions()); - expect(bucketInterval!.toString()).toEqual('P0D'); - expect(JSON.stringify(chartData)).toEqual(JSON.stringify(expectedChartData)); - }); - it('should return an empty object if response or timeInterval is undefined', () => { expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), response: undefined, timeInterval: undefined, }) ).toEqual({}); expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), response: undefined, }) ).toEqual({}); expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), timeInterval: undefined, }) diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.ts b/src/plugins/unified_histogram/public/chart/build_bucket_interval.ts similarity index 68% rename from src/plugins/unified_histogram/public/chart/build_chart_data.ts rename to src/plugins/unified_histogram/public/chart/build_bucket_interval.ts index 03b208802ac4d..b3c9671662dbc 100644 --- a/src/plugins/unified_histogram/public/chart/build_chart_data.ts +++ b/src/plugins/unified_histogram/public/chart/build_bucket_interval.ts @@ -9,42 +9,38 @@ import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { DataPublicPluginStart, search, tabifyAggResponse } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/common'; +import type { TimeRange } from '@kbn/es-query'; import type { UnifiedHistogramBucketInterval } from '../types'; -import { buildPointSeriesData } from './build_point_series_data'; import { getChartAggConfigs } from './get_chart_agg_configs'; -import { getDimensions } from './get_dimensions'; /** * Convert the response from the chart request into a format that can be used * by the unified histogram chart. The returned object should be used to update - * {@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}. + * time range interval of histogram. */ -export const buildChartData = ({ +export const buildBucketInterval = ({ data, dataView, timeInterval, + timeRange, response, }: { data: DataPublicPluginStart; dataView: DataView; timeInterval?: string; + timeRange: TimeRange; response?: SearchResponse; }) => { if (!timeInterval || !response) { return {}; } - const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); + const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, timeRange, data }); const bucketAggConfig = chartAggConfigs.aggs[1]; - const tabifiedData = tabifyAggResponse(chartAggConfigs, response); - const dimensions = getDimensions(chartAggConfigs, data); - const bucketInterval = search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) + + tabifyAggResponse(chartAggConfigs, response); + + return search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) ? (bucketAggConfig?.buckets?.getInterval() as UnifiedHistogramBucketInterval) : undefined; - const chartData = buildPointSeriesData(tabifiedData, dimensions!); - - return { - bucketInterval, - chartData, - }; }; diff --git a/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts deleted file mode 100644 index 3a7f81aa4cd40..0000000000000 --- a/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { buildPointSeriesData } from './build_point_series_data'; -import moment from 'moment'; -import type { Unit } from '@kbn/datemath'; - -describe('buildPointSeriesData', () => { - test('with valid data', () => { - const table = { - type: 'datatable', - columns: [ - { - id: 'col-0-2', - name: 'order_date per 30 days', - meta: { - type: 'date', - field: 'order_date', - index: 'kibana_sample_data_ecommerce', - params: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - source: 'esaggs', - sourceParams: { - dataViewId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - id: '2', - enabled: true, - type: 'date_histogram', - params: { - field: 'order_date', - timeRange: { from: 'now-15y', to: 'now' }, - useNormalizedEsInterval: true, - scaleMetricValues: false, - interval: 'auto', - used_interval: '30d', - drop_partials: false, - min_doc_count: 1, - extended_bounds: {}, - }, - schema: 'segment', - }, - }, - }, - { - id: 'col-1-1', - name: 'Count', - meta: { - type: 'number', - index: 'kibana_sample_data_ecommerce', - params: { id: 'number' }, - source: 'esaggs', - sourceParams: { - dataViewId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - id: '1', - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - }, - }, - ], - rows: [{ 'col-0-2': 1625176800000, 'col-1-1': 2139 }], - }; - const dimensions = { - x: { - accessor: 0, - label: 'order_date per 30 days', - format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - params: { - date: true, - interval: moment.duration(30, 'd'), - intervalESValue: 30, - intervalESUnit: 'd' as Unit, - format: 'YYYY-MM-DD', - bounds: { - min: moment('2006-07-29T11:08:13.078Z'), - max: moment('2021-07-29T11:08:13.078Z'), - }, - }, - }, - y: { accessor: 1, format: { id: 'number' }, label: 'Count' }, - } as const; - expect(buildPointSeriesData(table, dimensions)).toMatchInlineSnapshot(` - Object { - "ordered": Object { - "date": true, - "interval": "P30D", - "intervalESUnit": "d", - "intervalESValue": 30, - "max": "2021-07-29T11:08:13.078Z", - "min": "2006-07-29T11:08:13.078Z", - }, - "values": Array [ - Object { - "x": 1625176800000, - "y": 2139, - }, - ], - "xAxisFormat": Object { - "id": "date", - "params": Object { - "pattern": "YYYY-MM-DD", - }, - }, - "xAxisLabel": "order_date per 30 days", - "xAxisOrderedValues": Array [ - 1625176800000, - ], - "yAxisFormat": Object { - "id": "number", - }, - "yAxisLabel": "Count", - } - `); - }); -}); diff --git a/src/plugins/unified_histogram/public/chart/build_point_series_data.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.ts deleted file mode 100644 index dc9d97fd0708f..0000000000000 --- a/src/plugins/unified_histogram/public/chart/build_point_series_data.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { uniq } from 'lodash'; -import type { UnifiedHistogramChartData, Dimensions, Table } from '../types'; - -export const buildPointSeriesData = ( - table: Table, - dimensions: Dimensions -): UnifiedHistogramChartData => { - const { x, y } = dimensions; - const xAccessor = table.columns[x.accessor].id; - const yAccessor = table.columns[y.accessor].id; - const chart = {} as UnifiedHistogramChartData; - - chart.xAxisOrderedValues = uniq(table.rows.map((r) => r[xAccessor] as number)); - chart.xAxisFormat = x.format; - chart.xAxisLabel = table.columns[x.accessor].name; - chart.yAxisFormat = y.format; - const { intervalESUnit, intervalESValue, interval, bounds } = x.params; - chart.ordered = { - date: true, - interval, - intervalESUnit, - intervalESValue, - min: bounds.min, - max: bounds.max, - }; - - chart.yAxisLabel = table.columns[y.accessor].name; - - chart.values = table.rows - .filter((row) => row && row[yAccessor] !== 'NaN') - .map((row) => ({ - x: row[xAccessor] as number, - y: row[yAccessor] as number, - })); - - return chart; -}; diff --git a/src/plugins/unified_histogram/public/chart/chart.test.tsx b/src/plugins/unified_histogram/public/chart/chart.test.tsx index 41de0687acfa6..21682cb919d3c 100644 --- a/src/plugins/unified_histogram/public/chart/chart.test.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.test.tsx @@ -9,70 +9,50 @@ import React, { ReactElement } from 'react'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { UnifiedHistogramFetchStatus } from '../types'; import { Chart } from './chart'; import type { ReactWrapper } from 'enzyme'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { of } from 'rxjs'; import { HitsCounter } from '../hits_counter'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { dataViewMock } from '../__mocks__/data_view'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { Histogram } from './histogram'; async function mountComponent({ noChart, noHits, + noBreakdown, chartHidden = false, appendHistogram, onEditVisualization = jest.fn(), + dataView = dataViewWithTimefieldMock, }: { noChart?: boolean; noHits?: boolean; + noBreakdown?: boolean; chartHidden?: boolean; appendHistogram?: ReactElement; + dataView?: DataView; onEditVisualization?: null | (() => void); } = {}) { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: noHits ? 0 : 2 } } })) + ); const props = { + dataView, services: unifiedHistogramServicesMock, hits: noHits ? undefined @@ -91,8 +71,8 @@ async function mountComponent({ description: 'test', scale: 2, }, - data: chartData, }, + breakdown: noBreakdown ? undefined : { field: undefined }, appendHistogram, onEditVisualization: onEditVisualization || undefined, onResetChartHeight: jest.fn(), @@ -105,7 +85,7 @@ async function mountComponent({ instance = mountWithIntl(); // wait for initial async loading to complete await new Promise((r) => setTimeout(r, 0)); - await instance.update(); + instance.update(); }); return instance; } @@ -158,13 +138,13 @@ describe('Chart', () => { const fn = jest.fn(); const component = await mountComponent({ onEditVisualization: fn }); await act(async () => { - await component + component .find('[data-test-subj="unifiedHistogramEditVisualization"]') .first() .simulate('click'); }); - - expect(fn).toHaveBeenCalled(); + const lensAttributes = component.find(Histogram).prop('lensAttributes'); + expect(fn).toHaveBeenCalledWith(lensAttributes); }); it('should render HitsCounter when hits is defined', async () => { @@ -182,4 +162,29 @@ describe('Chart', () => { const component = await mountComponent({ appendHistogram }); expect(component.find('[data-test-subj="appendHistogram"]').exists()).toBeTruthy(); }); + + it('should not render chart if data view is not time based', async () => { + const component = await mountComponent({ dataView: dataViewMock }); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeFalsy(); + }); + + it('should render chart if data view is time based', async () => { + const component = await mountComponent(); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeTruthy(); + }); + + it('should render BreakdownFieldSelector when chart is visible and breakdown is defined', async () => { + const component = await mountComponent(); + expect(component.find(BreakdownFieldSelector).exists()).toBeTruthy(); + }); + + it('should not render BreakdownFieldSelector when chart is hidden', async () => { + const component = await mountComponent({ chartHidden: true }); + expect(component.find(BreakdownFieldSelector).exists()).toBeFalsy(); + }); + + it('should not render BreakdownFieldSelector when chart is visible and breakdown is undefined', async () => { + const component = await mountComponent({ noBreakdown: true }); + expect(component.find(BreakdownFieldSelector).exists()).toBeFalsy(); + }); }); diff --git a/src/plugins/unified_histogram/public/chart/chart.tsx b/src/plugins/unified_histogram/public/chart/chart.tsx index 0f6c47f8a532e..b1970cd26e365 100644 --- a/src/plugins/unified_histogram/public/chart/chart.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.tsx @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import type { ReactElement } from 'react'; -import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; -import moment from 'moment'; +import { ReactElement, useMemo } from 'react'; +import React, { memo } from 'react'; import { EuiButtonIcon, EuiContextMenu, @@ -16,31 +15,48 @@ import { EuiFlexItem, EuiPopover, EuiToolTip, - useEuiBreakpoint, - useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { css } from '@emotion/react'; +import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { HitsCounter } from '../hits_counter'; import { Histogram } from './histogram'; import { useChartPanels } from './use_chart_panels'; import type { + UnifiedHistogramBreakdownContext, UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, UnifiedHistogramHitsContext, + UnifiedHistogramChartLoadEvent, + UnifiedHistogramRequestContext, UnifiedHistogramServices, } from '../types'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { useTotalHits } from './use_total_hits'; +import { useRequestParams } from './use_request_params'; +import { useChartStyles } from './use_chart_styles'; +import { useChartActions } from './use_chart_actions'; +import { useRefetchId } from './use_refetch_id'; +import { getLensAttributes } from './get_lens_attributes'; export interface ChartProps { className?: string; services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime?: number; + request?: UnifiedHistogramRequestContext; hits?: UnifiedHistogramHitsContext; chart?: UnifiedHistogramChartContext; + breakdown?: UnifiedHistogramBreakdownContext; appendHitsCounter?: ReactElement; appendHistogram?: ReactElement; - onEditVisualization?: () => void; + onEditVisualization?: (lensAttributes: TypedLensByValueInput['attributes']) => void; onResetChartHeight?: () => void; onChartHiddenChange?: (chartHidden: boolean) => void; onTimeIntervalChange?: (timeInterval: string) => void; + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } const HistogramMemoized = memo(Histogram); @@ -48,89 +64,124 @@ const HistogramMemoized = memo(Histogram); export function Chart({ className, services, + dataView, + lastReloadRequestTime, + request, hits, chart, + breakdown, appendHitsCounter, appendHistogram, - onEditVisualization, + onEditVisualization: originalOnEditVisualization, onResetChartHeight, onChartHiddenChange, onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, }: ChartProps) { - const { data } = services; - const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); - - const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({ - element: null, - moveFocus: false, + const { + showChartOptionsPopover, + chartRef, + toggleChartOptions, + closeChartOptions, + toggleHideChart, + } = useChartActions({ + chart, + onChartHiddenChange, }); - const onShowChartOptions = useCallback(() => { - setShowChartOptionsPopover(!showChartOptionsPopover); - }, [showChartOptionsPopover]); + const panels = useChartPanels({ + chart, + toggleHideChart, + onTimeIntervalChange, + closePopover: closeChartOptions, + onResetChartHeight, + }); - const closeChartOptions = useCallback(() => { - setShowChartOptionsPopover(false); - }, [setShowChartOptionsPopover]); + const chartVisible = !!( + chart && + !chart.hidden && + dataView.id && + dataView.type !== DataViewType.ROLLUP && + dataView.isTimeBased() + ); - useEffect(() => { - if (chartRef.current.moveFocus && chartRef.current.element) { - chartRef.current.element.focus(); - } - }, [chart?.hidden]); + const { filters, query, relativeTimeRange } = useRequestParams({ + services, + lastReloadRequestTime, + request, + }); - const toggleHideChart = useCallback(() => { - const chartHidden = !chart?.hidden; - chartRef.current.moveFocus = !chartHidden; - onChartHiddenChange?.(chartHidden); - }, [chart?.hidden, onChartHiddenChange]); + const refetchId = useRefetchId({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, + }); - const timefilterUpdateHandler = useCallback( - (ranges: { from: number; to: number }) => { - data.query.timefilter.timefilter.setTime({ - from: moment(ranges.from).toISOString(), - to: moment(ranges.to).toISOString(), - mode: 'absolute', - }); - }, - [data] + // We need to update the absolute time range whenever the refetchId changes + const timeRange = useMemo( + () => services.data.query.timefilter.timefilter.getAbsoluteTime(), + // eslint-disable-next-line react-hooks/exhaustive-deps + [services.data.query.timefilter.timefilter, refetchId] ); - const panels = useChartPanels({ + useTotalHits({ + services, + dataView, + lastReloadRequestTime, + request, + hits, chart, - toggleHideChart, - onTimeIntervalChange: (timeInterval) => onTimeIntervalChange?.(timeInterval), - closePopover: () => setShowChartOptionsPopover(false), - onResetChartHeight, + chartVisible, + breakdown, + filters, + query, + timeRange, + refetchId, + onTotalHitsChange, }); - const { euiTheme } = useEuiTheme(); - const resultCountCss = css` - padding: ${euiTheme.size.s}; - min-height: ${euiTheme.base * 3}px; - `; - const resultCountTitleCss = css` - ${useEuiBreakpoint(['xs', 's'])} { - margin-bottom: 0 !important; - } - `; - const resultCountToggleCss = css` - ${useEuiBreakpoint(['xs', 's'])} { - align-items: flex-end; - } - `; - const timechartCss = css` - flex-grow: 1; - display: flex; - flex-direction: column; - position: relative; + const { + resultCountCss, + resultCountInnerCss, + resultCountTitleCss, + resultCountToggleCss, + histogramCss, + breakdownFieldSelectorGroupCss, + breakdownFieldSelectorItemCss, + chartToolButtonCss, + } = useChartStyles(chartVisible); - // SASSTODO: the visualizing component should have an option or a modifier - .series > rect { - fill-opacity: 0.5; - stroke-width: 1; - } - `; + const lensAttributes = useMemo( + () => + getLensAttributes({ + title: chart?.title, + filters, + query, + dataView, + timeInterval: chart?.timeInterval, + breakdownField: breakdown?.field, + }), + [breakdown?.field, chart?.timeInterval, chart?.title, dataView, filters, query] + ); + + const onEditVisualization = useMemo( + () => + originalOnEditVisualization + ? () => { + originalOnEditVisualization(lensAttributes); + } + : undefined, + [lensAttributes, originalOnEditVisualization] + ); return ( - + } {chart && ( - - + + + {chartVisible && breakdown && ( + + + + )} {onEditVisualization && ( - + )} - + - {chart && !chart.hidden && ( + {chartVisible && (
(chartRef.current.element = element)} @@ -212,12 +283,19 @@ export function Chart({ aria-label={i18n.translate('unifiedHistogram.histogramOfFoundDocumentsAriaLabel', { defaultMessage: 'Histogram of found documents', })} - css={timechartCss} + css={histogramCss} >
{appendHistogram} diff --git a/src/plugins/discover/public/application/main/components/loading_spinner/discover_field_visualize.stories.tsx b/src/plugins/unified_histogram/public/chart/consts.ts similarity index 59% rename from src/plugins/discover/public/application/main/components/loading_spinner/discover_field_visualize.stories.tsx rename to src/plugins/unified_histogram/public/chart/consts.ts index e61ac272c182f..d2af2ed4ee33a 100644 --- a/src/plugins/discover/public/application/main/components/loading_spinner/discover_field_visualize.stories.tsx +++ b/src/plugins/unified_histogram/public/chart/consts.ts @@ -6,10 +6,4 @@ * Side Public License, v 1. */ -import { storiesOf } from '@storybook/react'; -import React from 'react'; -import { LoadingSpinner } from './loading_spinner'; - -storiesOf('components/loading_spinner/LoadingSpinner', module).add('default', () => ( - -)); +export const REQUEST_DEBOUNCE_MS = 100; diff --git a/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts new file mode 100644 index 0000000000000..b38b42cf2a249 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts @@ -0,0 +1,35 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +describe('fieldSupportsBreakdown', () => { + it('should return false if field is not aggregatable', () => { + expect( + fieldSupportsBreakdown({ aggregatable: false, scripted: false, type: 'string' } as any) + ).toBe(false); + }); + + it('should return false if field is scripted', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: true, type: 'string' } as any) + ).toBe(false); + }); + + it('should return false if field type is not supported', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: false, type: 'unsupported' } as any) + ).toBe(false); + }); + + it('should return true if field is aggregatable and type is supported', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: false, type: 'string' } as any) + ).toBe(true); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts new file mode 100644 index 0000000000000..302a5950fefcb --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts @@ -0,0 +1,14 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataViewField } from '@kbn/data-views-plugin/public'; + +const supportedTypes = new Set(['string', 'boolean', 'number', 'ip']); + +export const fieldSupportsBreakdown = (field: DataViewField) => + supportedTypes.has(field.type) && field.aggregatable && !field.scripted; diff --git a/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts index 3b4f470ba6119..ef5ce1b677153 100644 --- a/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts @@ -14,7 +14,15 @@ describe('getChartAggConfigs', () => { test('is working', () => { const dataView = dataViewWithTimefieldMock; const dataMock = dataPluginMock.createStartContract(); - const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); + const aggsConfig = getChartAggConfigs({ + dataView, + timeInterval: 'auto', + data: dataMock, + timeRange: { + from: '2022-10-05T16:00:00.000-03:00', + to: '2022-10-05T18:00:00.000-03:00', + }, + }); expect(aggsConfig!.aggs).toMatchInlineSnapshot(` Array [ @@ -38,6 +46,10 @@ describe('getChartAggConfigs', () => { "interval": "auto", "min_doc_count": 1, "scaleMetricValues": false, + "timeRange": Object { + "from": "2022-10-05T16:00:00.000-03:00", + "to": "2022-10-05T18:00:00.000-03:00", + }, "useNormalizedEsInterval": true, "used_interval": "0ms", }, diff --git a/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts index 93ef7f3dd9188..d68330a22a45d 100644 --- a/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts @@ -8,6 +8,7 @@ import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/common'; +import type { TimeRange } from '@kbn/es-query'; /** * Helper function to get the agg configs required for the unified histogram chart request @@ -15,10 +16,12 @@ import type { DataView } from '@kbn/data-views-plugin/common'; export function getChartAggConfigs({ dataView, timeInterval, + timeRange, data, }: { dataView: DataView; timeInterval: string; + timeRange: TimeRange; data: DataPublicPluginStart; }) { const visStateAggs = [ @@ -32,7 +35,7 @@ export function getChartAggConfigs({ params: { field: dataView.timeFieldName!, interval: timeInterval, - timeRange: data.query.timefilter.timefilter.getTime(), + timeRange, }, }, ]; diff --git a/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts deleted file mode 100644 index fd26fa20ce793..0000000000000 --- a/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; -import { getDimensions } from './get_dimensions'; -import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; -import { calculateBounds } from '@kbn/data-plugin/public'; -import { getChartAggConfigs } from './get_chart_agg_configs'; - -test('getDimensions', () => { - const dataView = dataViewWithTimefieldMock; - const dataMock = dataPluginMock.createStartContract(); - dataMock.query.timefilter.timefilter.getTime = () => { - return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; - }; - dataMock.query.timefilter.timefilter.calculateBounds = (timeRange) => { - return calculateBounds(timeRange); - }; - const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); - const actual = getDimensions(aggsConfig!, dataMock); - expect(actual).toMatchInlineSnapshot(` - Object { - "x": Object { - "accessor": 0, - "format": Object { - "id": "date", - "params": Object { - "pattern": "HH:mm:ss.SSS", - }, - }, - "label": "timestamp per 0 milliseconds", - "params": Object { - "bounds": Object { - "max": "2021-03-29T07:04:00.695Z", - "min": "1991-03-29T08:04:00.694Z", - }, - "date": true, - "format": "HH:mm:ss.SSS", - "interval": "P0D", - "intervalESUnit": "ms", - "intervalESValue": 0, - }, - }, - "y": Object { - "accessor": 1, - "format": Object { - "id": "number", - }, - "label": "Count", - }, - } - `); -}); diff --git a/src/plugins/unified_histogram/public/chart/get_dimensions.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.ts deleted file mode 100644 index 94ed3d4540d21..0000000000000 --- a/src/plugins/unified_histogram/public/chart/get_dimensions.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import moment from 'moment'; -import dateMath from '@kbn/datemath'; -import { DataPublicPluginStart, search, IAggConfigs } from '@kbn/data-plugin/public'; -import type { Dimensions, HistogramParamsBounds } from '../types'; - -export function getDimensions( - aggs: IAggConfigs, - data: DataPublicPluginStart -): Dimensions | undefined { - const [metric, agg] = aggs.aggs; - const { from, to } = data.query.timefilter.timefilter.getTime(); - agg.params.timeRange = { - from: dateMath.parse(from), - to: dateMath.parse(to, { roundUp: true }), - }; - const bounds = agg.params.timeRange - ? (data.query.timefilter.timefilter.calculateBounds( - agg.params.timeRange - ) as HistogramParamsBounds) - : null; - const buckets = search.aggs.isDateHistogramBucketAggConfig(agg) ? agg.buckets : undefined; - - if (!buckets || !bounds) { - return; - } - - const { esUnit, esValue } = buckets.getInterval(); - return { - x: { - accessor: 0, - label: agg.makeLabel(), - format: agg.toSerializedFieldFormat(), - params: { - date: true, - interval: moment.duration(esValue, esUnit), - intervalESValue: esValue, - intervalESUnit: esUnit, - format: buckets.getScaledDateFormat(), - bounds, - }, - }, - y: { - accessor: 1, - format: metric.toSerializedFieldFormat(), - label: metric.makeLabel(), - }, - }; -} diff --git a/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts b/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts new file mode 100644 index 0000000000000..3e0ac936a6573 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts @@ -0,0 +1,480 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getLensAttributes } from './get_lens_attributes'; +import { AggregateQuery, Filter, FilterStateStore, Query } from '@kbn/es-query'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; + +describe('getLensAttributes', () => { + const dataView: DataView = dataViewWithTimefieldMock; + const filters: Filter[] = [ + { + meta: { + index: dataView.id, + negate: false, + disabled: false, + alias: null, + type: 'phrase', + key: 'extension', + params: { + query: 'js', + }, + }, + query: { + match: { + extension: { + query: 'js', + type: 'phrase', + }, + }, + }, + $state: { + store: FilterStateStore.APP_STATE, + }, + }, + ]; + const query: Query | AggregateQuery = { language: 'kuery', query: 'extension : css' }; + const timeInterval = 'auto'; + + it('should return correct attributes', () => { + const breakdownField: DataViewField | undefined = undefined; + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "date_column", + "count_column", + ], + "columns": Object { + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "date_column", + "yConfig": Array [ + Object { + "forAccessor": "count_column", + }, + ], + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); + + it('should return correct attributes with breakdown field', () => { + const breakdownField: DataViewField | undefined = dataView.fields.find( + (f) => f.name === 'extension' + ); + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "breakdown_column", + "date_column", + "count_column", + ], + "columns": Object { + "breakdown_column": Object { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of extension", + "operationType": "terms", + "params": Object { + "missingBucket": false, + "orderBy": Object { + "columnId": "count_column", + "type": "column", + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": Object { + "id": "terms", + }, + "size": 3, + }, + "scale": "ordinal", + "sourceField": "extension", + }, + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "splitAccessor": "breakdown_column", + "xAccessor": "date_column", + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); + + it('should return correct attributes with unsupported breakdown field', () => { + const breakdownField: DataViewField | undefined = dataView.fields.find( + (f) => f.name === 'scripted' + ); + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "date_column", + "count_column", + ], + "columns": Object { + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "date_column", + "yConfig": Array [ + Object { + "forAccessor": "count_column", + }, + ], + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts b/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts new file mode 100644 index 0000000000000..dc6f9216b4e56 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts @@ -0,0 +1,180 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Filter, Query } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; +import type { + CountIndexPatternColumn, + DateHistogramIndexPatternColumn, + GenericIndexPatternColumn, + TermsIndexPatternColumn, + TypedLensByValueInput, +} from '@kbn/lens-plugin/public'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +export const getLensAttributes = ({ + title, + filters, + query, + dataView, + timeInterval, + breakdownField, +}: { + title?: string; + filters: Filter[]; + query: Query | AggregateQuery; + dataView: DataView; + timeInterval: string | undefined; + breakdownField: DataViewField | undefined; +}) => { + const showBreakdown = breakdownField && fieldSupportsBreakdown(breakdownField); + + let columnOrder = ['date_column', 'count_column']; + + if (showBreakdown) { + columnOrder = ['breakdown_column', ...columnOrder]; + } + + let columns: Record = { + date_column: { + dataType: 'date', + isBucketed: true, + label: dataView.timeFieldName ?? '', + operationType: 'date_histogram', + scale: 'interval', + sourceField: dataView.timeFieldName, + params: { + interval: timeInterval ?? 'auto', + }, + } as DateHistogramIndexPatternColumn, + count_column: { + dataType: 'number', + isBucketed: false, + label: i18n.translate('unifiedHistogram.countColumnLabel', { + defaultMessage: 'Count of records', + }), + operationType: 'count', + scale: 'ratio', + sourceField: '___records___', + params: { + format: { + id: 'number', + params: { + decimals: 0, + }, + }, + }, + } as CountIndexPatternColumn, + }; + + if (showBreakdown) { + columns = { + ...columns, + breakdown_column: { + dataType: 'string', + isBucketed: true, + label: i18n.translate('unifiedHistogram.breakdownColumnLabel', { + defaultMessage: 'Top 3 values of {fieldName}', + values: { fieldName: breakdownField?.displayName }, + }), + operationType: 'terms', + scale: 'ordinal', + sourceField: breakdownField.name, + params: { + size: 3, + orderBy: { + type: 'column', + columnId: 'count_column', + }, + orderDirection: 'desc', + otherBucket: true, + missingBucket: false, + parentFormat: { + id: 'terms', + }, + }, + } as TermsIndexPatternColumn, + }; + } + + return { + title: + title ?? + i18n.translate('unifiedHistogram.lensTitle', { + defaultMessage: 'Edit visualization', + }), + references: [ + { + id: dataView.id ?? '', + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: dataView.id ?? '', + name: 'indexpattern-datasource-layer-unifiedHistogram', + type: 'index-pattern', + }, + ], + state: { + datasourceStates: { + formBased: { + layers: { + unifiedHistogram: { columnOrder, columns }, + }, + }, + }, + filters, + query: 'language' in query ? query : { language: 'kuery', query: '' }, + visualization: { + layers: [ + { + accessors: ['count_column'], + layerId: 'unifiedHistogram', + layerType: 'data', + seriesType: 'bar_stacked', + xAccessor: 'date_column', + ...(showBreakdown + ? { splitAccessor: 'breakdown_column' } + : { + yConfig: [ + { + forAccessor: 'count_column', + }, + ], + }), + }, + ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'bar_stacked', + valueLabels: 'hide', + fittingFunction: 'None', + showCurrentTimeMarker: true, + axisTitlesVisibilitySettings: { + x: false, + yLeft: false, + yRight: false, + }, + gridlinesVisibilitySettings: { + x: true, + yLeft: true, + yRight: false, + }, + tickLabelsVisibilitySettings: { + x: true, + yLeft: true, + yRight: false, + }, + }, + }, + visualizationType: 'lnsXY', + } as TypedLensByValueInput['attributes']; +}; diff --git a/src/plugins/unified_histogram/public/chart/histogram.test.tsx b/src/plugins/unified_histogram/public/chart/histogram.test.tsx index 3e1213978e385..03652a63f5456 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.test.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.test.tsx @@ -6,55 +6,37 @@ * Side Public License, v 1. */ import { mountWithIntl } from '@kbn/test-jest-helpers'; -import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; -import { Histogram } from './histogram'; +import { getLensProps, Histogram } from './histogram'; import React from 'react'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { createDefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import { UnifiedHistogramFetchStatus } from '../types'; +import { getLensAttributes } from './get_lens_attributes'; +import { REQUEST_DEBOUNCE_MS } from './consts'; +import { act } from 'react-dom/test-utils'; +import * as buildBucketInterval from './build_bucket_interval'; +import * as useTimeRange from './use_time_range'; +import { RequestStatus } from '@kbn/inspector-plugin/public'; -const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), +const mockBucketInterval = { description: '1 minute', scale: undefined, scaled: false }; +jest.spyOn(buildBucketInterval, 'buildBucketInterval').mockReturnValue(mockBucketInterval); +jest.spyOn(useTimeRange, 'useTimeRange'); + +const getMockLensAttributes = () => + getLensAttributes({ + title: 'test', + filters: [], + query: { + language: 'kuery', + query: '', }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], -} as unknown as UnifiedHistogramChartData; + dataView: dataViewWithTimefieldMock, + timeInterval: 'auto', + breakdownField: dataViewWithTimefieldMock.getFieldByName('extension'), + }); -function mountComponent( - status: UnifiedHistogramFetchStatus, - data: UnifiedHistogramChartData | null = chartData, - error?: Error -) { +function mountComponent() { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; @@ -64,44 +46,212 @@ function mountComponent( const props = { services: unifiedHistogramServicesMock, + request: { + searchSessionId: '123', + }, + hits: { + status: UnifiedHistogramFetchStatus.loading, + total: undefined, + }, chart: { - status, hidden: false, timeInterval: 'auto', - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - data: data ?? undefined, - error, }, timefilterUpdateHandler, + dataView: dataViewWithTimefieldMock, + timeRange: { + from: '2020-05-14T11:05:13.590', + to: '2020-05-14T11:20:13.590', + }, + lastReloadRequestTime: 42, + lensAttributes: getMockLensAttributes(), + onTotalHitsChange: jest.fn(), + onChartLoad: jest.fn(), }; - return mountWithIntl(); + return { + props, + component: mountWithIntl(), + }; } describe('Histogram', () => { it('renders correctly', () => { - const component = mountComponent('complete'); + const { component } = mountComponent(); expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); }); - it('renders error correctly', () => { - const component = mountComponent('error', null, new Error('Loading error')); - expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(false); - expect(component.find('[data-test-subj="unifiedHistogramErrorChartContainer"]').exists()).toBe( - true + it('should render lens.EmbeddableComponent with debounced props', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + expect(component.find(embeddable).exists()).toBe(true); + let lensProps = component.find(embeddable).props(); + const originalProps = getLensProps({ + timeRange: props.timeRange, + attributes: getMockLensAttributes(), + request: props.request, + lastReloadRequestTime: props.lastReloadRequestTime, + onLoad: lensProps.onLoad, + }); + expect(lensProps).toEqual(originalProps); + component.setProps({ lastReloadRequestTime: 43 }).update(); + lensProps = component.find(embeddable).props(); + expect(lensProps).toEqual(originalProps); + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, REQUEST_DEBOUNCE_MS)); + }); + component.update(); + lensProps = component.find(embeddable).props(); + expect(lensProps).toEqual({ ...originalProps, lastReloadRequestTime: 43 }); + }); + + it('should execute onLoad correctly', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + adapters.tables.tables.unifiedHistogram = { meta: { statistics: { totalCount: 100 } } } as any; + const rawResponse = { + took: 0, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: 100, + max_score: null, + hits: [], + }, + aggregations: { + '2': { + buckets: [ + { + key_as_string: '2022-10-05T16:00:00.000-03:00', + key: 1664996400000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T16:30:00.000-03:00', + key: 1664998200000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T17:00:00.000-03:00', + key: 1665000000000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T17:30:00.000-03:00', + key: 1665001800000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T18:00:00.000-03:00', + key: 1665003600000, + doc_count: 20, + }, + ], + }, + }, + }; + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ response: { json: { rawResponse } } } as any]); + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters: {} }); + expect(buildBucketInterval.buildBucketInterval).not.toHaveBeenCalled(); + expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( + expect.objectContaining({ bucketInterval: undefined }) + ); + act(() => { + onLoad(false, adapters); + }); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.complete, + 100 + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: true, adapters }); + expect(buildBucketInterval.buildBucketInterval).toHaveBeenCalled(); + expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( + expect.objectContaining({ bucketInterval: mockBucketInterval }) ); - expect( - component.find('[data-test-subj="unifiedHistogramErrorChartText"]').get(1).props.children - ).toBe('Loading error'); }); - it('renders loading state correctly', () => { - const component = mountComponent('loading', null); - expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); - expect(component.find('[data-test-subj="unifiedHistogramChartLoading"]').exists()).toBe(true); + it('should execute onLoad correctly when the request has a failure status', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ status: RequestStatus.ERROR } as any]); + onLoad(false, adapters); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.error, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters }); + }); + + it('should execute onLoad correctly when the response has shard failures', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + const rawResponse = { + _shards: { + total: 1, + successful: 0, + skipped: 0, + failed: 1, + failures: [], + }, + }; + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ response: { json: { rawResponse } } } as any]); + onLoad(false, adapters); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.error, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters }); + }); + + it('should not recreate onLoad in debounced lens props when hits.total changes', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + undefined + ); + component + .setProps({ + hits: { + status: UnifiedHistogramFetchStatus.complete, + total: 100, + }, + }) + .update(); + expect(component.find(embeddable).props().onLoad).toBe(onLoad); + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, REQUEST_DEBOUNCE_MS)); + }); + component.update(); + expect(component.find(embeddable).props().onLoad).toBe(onLoad); + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + 100 + ); }); }); diff --git a/src/plugins/unified_histogram/public/chart/histogram.tsx b/src/plugins/unified_histogram/public/chart/histogram.tsx index a201258e49bf2..c30c6a1410985 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.tsx @@ -6,351 +6,187 @@ * Side Public License, v 1. */ -import moment, { unitOfTime } from 'moment-timezone'; -import React, { useCallback, useMemo } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiIconTip, - EuiLoadingChart, - EuiSpacer, - EuiText, - useEuiTheme, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import dateMath from '@kbn/datemath'; -import type { - BrushEndListener, - ElementClickListener, - XYBrushEvent, - XYChartElementEvent, -} from '@elastic/charts'; -import { - Axis, - Chart, - HistogramBarSeries, - Position, - ScaleType, - Settings, - TooltipType, -} from '@elastic/charts'; -import type { IUiSettingsClient } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; -import { - CurrentTime, - Endzones, - getAdjustedInterval, - renderEndzoneTooltip, -} from '@kbn/charts-plugin/public'; -import { LEGACY_TIME_AXIS, MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; +import { useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; -import type { UnifiedHistogramChartContext, UnifiedHistogramServices } from '../types'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import type { IKibanaSearchResponse } from '@kbn/data-plugin/public'; +import type { estypes } from '@elastic/elasticsearch'; +import type { TimeRange } from '@kbn/es-query'; +import useDebounce from 'react-use/lib/useDebounce'; +import { ViewMode } from '@kbn/embeddable-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import { RequestStatus } from '@kbn/inspector-plugin/public'; +import { + UnifiedHistogramBucketInterval, + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, + UnifiedHistogramChartLoadEvent, + UnifiedHistogramRequestContext, + UnifiedHistogramServices, +} from '../types'; +import { buildBucketInterval } from './build_bucket_interval'; +import { useTimeRange } from './use_time_range'; +import { REQUEST_DEBOUNCE_MS } from './consts'; export interface HistogramProps { services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime: number | undefined; + request?: UnifiedHistogramRequestContext; + hits?: UnifiedHistogramHitsContext; chart: UnifiedHistogramChartContext; - timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; -} - -function getTimezone(uiSettings: IUiSettingsClient) { - if (uiSettings.isDefault('dateFormat:tz')) { - const detectedTimezone = moment.tz.guess(); - if (detectedTimezone) return detectedTimezone; - else return moment().format('Z'); - } else { - return uiSettings.get('dateFormat:tz', 'Browser'); - } + timeRange: TimeRange; + lensAttributes: TypedLensByValueInput['attributes']; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } export function Histogram({ - services: { data, theme, uiSettings, fieldFormats }, - chart: { status, timeInterval, bucketInterval, data: chartData, error }, - timefilterUpdateHandler, + services: { data, lens, uiSettings }, + dataView, + lastReloadRequestTime, + request, + hits, + chart: { timeInterval }, + timeRange, + lensAttributes: attributes, + onTotalHitsChange, + onChartLoad, }: HistogramProps) { - const chartTheme = theme.useChartsTheme(); - const chartBaseTheme = theme.useChartsBaseTheme(); - const timeZone = getTimezone(uiSettings); + const [bucketInterval, setBucketInterval] = useState(); + const { timeRangeText, timeRangeDisplay } = useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }); - const onBrushEnd = useCallback( - ({ x }: XYBrushEvent) => { - if (!x) { + // Keep track of previous hits in a ref to avoid recreating the + // onLoad callback when the hits change, which triggers a Lens reload + const previousHits = useRef(hits?.total); + + useEffect(() => { + previousHits.current = hits?.total; + }, [hits?.total]); + + const onLoad = useCallback( + (isLoading: boolean, adapters: Partial | undefined) => { + const lensRequest = adapters?.requests?.getRequests()[0]; + const requestFailed = lensRequest?.status === RequestStatus.ERROR; + const json = lensRequest?.response?.json as + | IKibanaSearchResponse + | undefined; + const response = json?.rawResponse; + + // Lens will swallow shard failures and return `isLoading: false` because it displays + // its own errors, but this causes us to emit onTotalHitsChange(UnifiedHistogramFetchStatus.complete, 0). + // This is incorrect, so we check for request failures and shard failures here, and emit an error instead. + if (requestFailed || response?._shards.failed) { + onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, undefined); + onChartLoad?.({ complete: false, adapters: adapters ?? {} }); return; } - const [from, to] = x; - timefilterUpdateHandler({ from, to }); - }, - [timefilterUpdateHandler] - ); - const onElementClick = useCallback( - (xInterval: number): ElementClickListener => - ([elementData]) => { - const startRange = (elementData as XYChartElementEvent)[0].x; + const totalHits = adapters?.tables?.tables?.unifiedHistogram?.meta?.statistics?.totalCount; - const range = { - from: startRange, - to: startRange + xInterval, - }; + onTotalHitsChange?.( + isLoading ? UnifiedHistogramFetchStatus.loading : UnifiedHistogramFetchStatus.complete, + totalHits ?? previousHits.current + ); - timefilterUpdateHandler(range); - }, - [timefilterUpdateHandler] - ); + if (response) { + const newBucketInterval = buildBucketInterval({ + data, + dataView, + timeInterval, + timeRange, + response, + }); - const { timefilter } = data.query.timefilter; - const { from, to } = timefilter.getAbsoluteTime(); - const dateFormat = useMemo(() => uiSettings.get('dateFormat'), [uiSettings]); - - const toMoment = useCallback( - (datetime: moment.Moment | undefined) => { - if (!datetime) { - return ''; - } - if (!dateFormat) { - return String(datetime); + setBucketInterval(newBucketInterval); } - return datetime.format(dateFormat); + + onChartLoad?.({ complete: !isLoading, adapters: adapters ?? {} }); }, - [dateFormat] + [data, dataView, onChartLoad, onTotalHitsChange, timeInterval, timeRange] ); - const timeRangeText = useMemo(() => { - const timeRange = { - from: dateMath.parse(from), - to: dateMath.parse(to, { roundUp: true }), - }; - const intervalText = i18n.translate('unifiedHistogram.histogramTimeRangeIntervalDescription', { - defaultMessage: '(interval: {value})', - values: { - value: `${ - timeInterval === 'auto' - ? `${i18n.translate('unifiedHistogram.histogramTimeRangeIntervalAuto', { - defaultMessage: 'Auto', - })} - ` - : '' - }${bucketInterval?.description}`, - }, - }); - return `${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${intervalText}`; - }, [from, to, timeInterval, bucketInterval?.description, toMoment]); - const { euiTheme } = useEuiTheme(); const chartCss = css` + position: relative; flex-grow: 1; - padding: 0 ${euiTheme.size.s} ${euiTheme.size.s} ${euiTheme.size.s}; - `; - if (!chartData && status === 'loading') { - const chartLoadingCss = css` - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 0 100%; - text-align: center; + & > div { height: 100%; - width: 100%; - `; - - return ( -
-
- - - - - -
-
- ); - } - - if (status === 'error' && error) { - const chartErrorContainerCss = css` - padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; - `; - const chartErrorIconCss = css` - padding-top: 0.5 * ${euiTheme.size.xs}; - `; - const chartErrorCss = css` - margin-left: ${euiTheme.size.xs} !important; - `; - const chartErrorTextCss = css` - margin-top: ${euiTheme.size.s}; - `; - - return ( -
- - - - - - - - - - - - {error.message} - -
- ); - } - - if (!chartData) { - return null; - } - - const formatXValue = (val: string) => { - const xAxisFormat = chartData.xAxisFormat.params!.pattern; - return moment(val).format(xAxisFormat); - }; - - const isDarkMode = uiSettings.get('theme:darkMode'); - - /* - * Deprecation: [interval] on [date_histogram] is deprecated, use [fixed_interval] or [calendar_interval]. - * see https://github.com/elastic/kibana/issues/27410 - * TODO: Once the Discover query has been update, we should change the below to use the new field - */ - const { intervalESValue, intervalESUnit, interval } = chartData.ordered; - const xInterval = interval.asMilliseconds(); - - const xValues = chartData.xAxisOrderedValues; - const lastXValue = xValues[xValues.length - 1]; - - const domain = chartData.ordered; - const domainStart = domain.min.valueOf(); - const domainEnd = domain.max.valueOf(); - - const domainMin = Math.min(chartData.values[0]?.x, domainStart); - const domainMax = Math.max(domainEnd - xInterval, lastXValue); - - const xDomain = { - min: domainMin, - max: domainMax, - minInterval: getAdjustedInterval( - xValues, - intervalESValue, - intervalESUnit as unitOfTime.Base, - timeZone - ), - }; - const tooltipProps = { - headerFormatter: renderEndzoneTooltip(xInterval, domainStart, domainEnd, formatXValue), - type: TooltipType.VerticalCursor, - }; - - const xAxisFormatter = fieldFormats.deserialize(chartData.yAxisFormat); - - const useLegacyTimeAxis = uiSettings.get(LEGACY_TIME_AXIS, false); + } + + & .echLegend .echLegendList { + padding-right: ${euiTheme.size.s}; + } + + & > .euiLoadingChart { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + `; - const toolTipTitle = i18n.translate('unifiedHistogram.timeIntervalWithValueWarning', { - defaultMessage: 'Warning', - }); + const [debouncedProps, setDebouncedProps] = useState( + getLensProps({ + timeRange, + attributes, + request, + lastReloadRequestTime, + onLoad, + }) + ); - const toolTipContent = i18n.translate('unifiedHistogram.bucketIntervalTooltip', { - defaultMessage: - 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}.', - values: { - bucketsDescription: - bucketInterval!.scale && bucketInterval!.scale > 1 - ? i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooLargeBucketsText', { - defaultMessage: 'buckets that are too large', - }) - : i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooManyBucketsText', { - defaultMessage: 'too many buckets', - }), - bucketIntervalDescription: bucketInterval?.description, + useDebounce( + () => { + setDebouncedProps( + getLensProps({ timeRange, attributes, request, lastReloadRequestTime, onLoad }) + ); }, - }); - - const timeRangeCss = css` - padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; - `; - let timeRange = ( - - {timeRangeText} - + REQUEST_DEBOUNCE_MS, + [attributes, lastReloadRequestTime, onLoad, request, timeRange] ); - if (bucketInterval?.scaled) { - const timeRangeWrapperCss = css` - flex-grow: 0; - `; - timeRange = ( - - {timeRange} - - - - - ); - } return ( - + <>
- - - xAxisFormatter.convert(value)} - /> - - - - - +
- {timeRange} -
+ {timeRangeDisplay} + ); } + +export const getLensProps = ({ + timeRange, + attributes, + request, + lastReloadRequestTime, + onLoad, +}: { + timeRange: TimeRange; + attributes: TypedLensByValueInput['attributes']; + request: UnifiedHistogramRequestContext | undefined; + lastReloadRequestTime: number | undefined; + onLoad: (isLoading: boolean, adapters: Partial | undefined) => void; +}) => ({ + id: 'unifiedHistogramLensComponent', + viewMode: ViewMode.VIEW, + timeRange, + attributes, + noPadding: true, + searchSessionId: request?.searchSessionId, + executionContext: { + description: 'fetch chart data and total hits', + }, + lastReloadRequestTime, + onLoad, +}); diff --git a/src/plugins/unified_histogram/public/chart/index.ts b/src/plugins/unified_histogram/public/chart/index.ts index e50532f3bfec2..6a6d2d65f6f92 100644 --- a/src/plugins/unified_histogram/public/chart/index.ts +++ b/src/plugins/unified_histogram/public/chart/index.ts @@ -7,5 +7,3 @@ */ export { Chart } from './chart'; -export { getChartAggConfigs } from './get_chart_agg_configs'; -export { buildChartData } from './build_chart_data'; diff --git a/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts b/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts new file mode 100644 index 0000000000000..5967f01fd543b --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts @@ -0,0 +1,82 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { act } from 'react-test-renderer'; +import { UnifiedHistogramChartContext } from '..'; +import { useChartActions } from './use_chart_actions'; + +describe('useChartActions', () => { + const render = () => { + const chart: UnifiedHistogramChartContext = { + hidden: false, + timeInterval: 'auto', + }; + const onChartHiddenChange = jest.fn((hidden: boolean) => { + chart.hidden = hidden; + }); + return { + chart, + onChartHiddenChange, + hook: renderHook(() => useChartActions({ chart, onChartHiddenChange })), + }; + }; + + it('should toggle chart options', () => { + const { hook } = render(); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(true); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + }); + + it('should close chart options', () => { + const { hook } = render(); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(true); + act(() => { + hook.result.current.closeChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + }); + + it('should toggle hide chart', () => { + const { chart, onChartHiddenChange, hook } = render(); + act(() => { + hook.result.current.toggleHideChart(); + }); + expect(chart.hidden).toBe(true); + expect(onChartHiddenChange).toBeCalledWith(true); + act(() => { + hook.result.current.toggleHideChart(); + }); + expect(chart.hidden).toBe(false); + expect(onChartHiddenChange).toBeCalledWith(false); + }); + + it('should focus chart element', () => { + const { chart, hook } = render(); + hook.result.current.chartRef.current.element = document.createElement('div'); + hook.result.current.chartRef.current.element.focus = jest.fn(); + chart.hidden = true; + hook.rerender(); + act(() => { + hook.result.current.toggleHideChart(); + }); + hook.rerender(); + expect(hook.result.current.chartRef.current.moveFocus).toBe(true); + expect(hook.result.current.chartRef.current.element.focus).toBeCalled(); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_chart_actions.ts b/src/plugins/unified_histogram/public/chart/use_chart_actions.ts new file mode 100644 index 0000000000000..85b876e0862c1 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_actions.ts @@ -0,0 +1,53 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useCallback, useEffect, useRef, useState } from 'react'; +import type { UnifiedHistogramChartContext } from '../types'; + +export const useChartActions = ({ + chart, + onChartHiddenChange, +}: { + chart: UnifiedHistogramChartContext | undefined; + onChartHiddenChange?: (chartHidden: boolean) => void; +}) => { + const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); + + const toggleChartOptions = useCallback(() => { + setShowChartOptionsPopover(!showChartOptionsPopover); + }, [showChartOptionsPopover]); + + const closeChartOptions = useCallback(() => { + setShowChartOptionsPopover(false); + }, [setShowChartOptionsPopover]); + + const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({ + element: null, + moveFocus: false, + }); + + useEffect(() => { + if (chartRef.current.moveFocus && chartRef.current.element) { + chartRef.current.element.focus(); + } + }, [chart?.hidden]); + + const toggleHideChart = useCallback(() => { + const chartHidden = !chart?.hidden; + chartRef.current.moveFocus = !chartHidden; + onChartHiddenChange?.(chartHidden); + }, [chart?.hidden, onChartHiddenChange]); + + return { + showChartOptionsPopover, + chartRef, + toggleChartOptions, + closeChartOptions, + toggleHideChart, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts b/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts index 71e2d3e4a705a..aec3f1a8e291f 100644 --- a/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts +++ b/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts @@ -19,7 +19,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight: jest.fn(), chart: { - status: 'complete', hidden: true, timeInterval: 'auto', }, @@ -39,7 +38,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight: jest.fn(), chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, @@ -59,7 +57,6 @@ describe('test useChartPanels', () => { onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, @@ -78,7 +75,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight, chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, diff --git a/src/plugins/unified_histogram/public/chart/use_chart_panels.ts b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts index dd6f162b352f6..8f2874baa624e 100644 --- a/src/plugins/unified_histogram/public/chart/use_chart_panels.ts +++ b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts @@ -23,7 +23,7 @@ export function useChartPanels({ }: { chart?: UnifiedHistogramChartContext; toggleHideChart: () => void; - onTimeIntervalChange: (timeInterval: string) => void; + onTimeIntervalChange?: (timeInterval: string) => void; closePopover: () => void; onResetChartHeight?: () => void; }) { @@ -107,7 +107,7 @@ export function useChartPanels({ label: display, icon: val === chart.timeInterval ? 'check' : 'empty', onClick: () => { - onTimeIntervalChange(val); + onTimeIntervalChange?.(val); closePopover(); }, 'data-test-subj': `unifiedHistogramTimeInterval-${display}`, diff --git a/src/plugins/unified_histogram/public/chart/use_chart_styles.tsx b/src/plugins/unified_histogram/public/chart/use_chart_styles.tsx new file mode 100644 index 0000000000000..c019c7cef981e --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_styles.tsx @@ -0,0 +1,75 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useEuiBreakpoint, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; + +export const useChartStyles = (chartVisible: boolean) => { + const { euiTheme } = useEuiTheme(); + const resultCountCss = css` + padding: ${euiTheme.size.s} ${euiTheme.size.s} ${chartVisible ? 0 : euiTheme.size.s} + ${euiTheme.size.s}; + min-height: ${euiTheme.base * 2.5}px; + `; + const resultCountInnerCss = css` + ${useEuiBreakpoint(['xs', 's'])} { + align-items: center; + } + `; + const resultCountTitleCss = css` + flex-basis: auto; + + ${useEuiBreakpoint(['xs', 's'])} { + margin-bottom: 0 !important; + } + `; + const resultCountToggleCss = css` + flex-basis: auto; + min-width: 0; + + ${useEuiBreakpoint(['xs', 's'])} { + align-items: flex-end; + } + `; + const histogramCss = css` + flex-grow: 1; + display: flex; + flex-direction: column; + position: relative; + + // SASSTODO: the visualizing component should have an option or a modifier + .series > rect { + fill-opacity: 0.5; + stroke-width: 1; + } + `; + const breakdownFieldSelectorGroupCss = css` + width: 100%; + `; + const breakdownFieldSelectorItemCss = css` + min-width: 0; + align-items: flex-end; + padding-left: ${euiTheme.size.s}; + `; + const chartToolButtonCss = css` + display: flex; + justify-content: center; + padding-left: ${euiTheme.size.s}; + `; + + return { + resultCountCss, + resultCountInnerCss, + resultCountTitleCss, + resultCountToggleCss, + histogramCss, + breakdownFieldSelectorGroupCss, + breakdownFieldSelectorItemCss, + chartToolButtonCss, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts b/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts new file mode 100644 index 0000000000000..8835173df2599 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts @@ -0,0 +1,68 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataView } from '@kbn/data-views-plugin/common'; +import { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { renderHook } from '@testing-library/react-hooks'; +import { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, +} from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { useRefetchId } from './use_refetch_id'; + +describe('useRefetchId', () => { + const getDeps: () => { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; + } = () => ({ + dataView: dataViewWithTimefieldMock, + lastReloadRequestTime: 0, + request: undefined, + hits: undefined, + chart: undefined, + chartVisible: true, + breakdown: undefined, + filters: [], + query: { language: 'kuery', query: '' }, + relativeTimeRange: { from: 'now-15m', to: 'now' }, + }); + + it('should increment the refetchId when any of the arguments change', () => { + const hook = renderHook((props) => useRefetchId(props), { initialProps: getDeps() }); + expect(hook.result.current).toBe(0); + hook.rerender(getDeps()); + expect(hook.result.current).toBe(0); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + }); + expect(hook.result.current).toBe(1); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + }); + expect(hook.result.current).toBe(1); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + query: { language: 'kuery', query: 'foo' }, + }); + expect(hook.result.current).toBe(2); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_refetch_id.ts b/src/plugins/unified_histogram/public/chart/use_refetch_id.ts new file mode 100644 index 0000000000000..4415be9ccd8b6 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_refetch_id.ts @@ -0,0 +1,121 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { cloneDeep, isEqual } from 'lodash'; +import { useEffect, useRef, useState } from 'react'; +import type { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, +} from '../types'; + +export const useRefetchId = ({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange: relativeTimeRange, +}: { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; +}) => { + const refetchDeps = useRef>(); + const [refetchId, setRefetchId] = useState(0); + + // When the unified histogram props change, we must compare the current subset + // that should trigger a histogram refetch against the previous subset. If they + // are different, we must refetch the histogram to ensure it's up to date. + useEffect(() => { + const newRefetchDeps = getRefetchDeps({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, + }); + + if (!isEqual(refetchDeps.current, newRefetchDeps)) { + if (refetchDeps.current) { + setRefetchId((id) => id + 1); + } + + refetchDeps.current = newRefetchDeps; + } + }, [ + breakdown, + chart, + chartVisible, + dataView, + filters, + hits, + lastReloadRequestTime, + query, + request, + relativeTimeRange, + ]); + + return refetchId; +}; + +const getRefetchDeps = ({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, +}: { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; +}) => + cloneDeep([ + dataView.id, + lastReloadRequestTime, + request?.searchSessionId, + Boolean(hits), + chartVisible, + chart?.timeInterval, + Boolean(breakdown), + breakdown?.field, + filters, + query, + relativeTimeRange, + ]); diff --git a/src/plugins/unified_histogram/public/chart/use_request_params.tsx b/src/plugins/unified_histogram/public/chart/use_request_params.tsx new file mode 100644 index 0000000000000..defa2bdd920d9 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_request_params.tsx @@ -0,0 +1,58 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { connectToQueryState, QueryState } from '@kbn/data-plugin/public'; +import { createStateContainer, useContainerState } from '@kbn/kibana-utils-plugin/public'; +import { useEffect, useMemo, useRef } from 'react'; +import type { UnifiedHistogramRequestContext, UnifiedHistogramServices } from '../types'; + +export const useRequestParams = ({ + services, + lastReloadRequestTime, + request, +}: { + services: UnifiedHistogramServices; + lastReloadRequestTime: number | undefined; + request?: UnifiedHistogramRequestContext; +}) => { + const { data } = services; + + const queryStateContainer = useRef( + createStateContainer({ + filters: data.query.filterManager.getFilters(), + query: data.query.queryString.getQuery(), + refreshInterval: data.query.timefilter.timefilter.getRefreshInterval(), + time: data.query.timefilter.timefilter.getTime(), + }) + ).current; + + const queryState = useContainerState(queryStateContainer); + + useEffect(() => { + return connectToQueryState(data.query, queryStateContainer, { + time: true, + query: true, + filters: true, + refreshInterval: true, + }); + }, [data.query, queryStateContainer]); + + const filters = useMemo(() => queryState.filters ?? [], [queryState.filters]); + + const query = useMemo( + () => queryState.query ?? data.query.queryString.getDefaultQuery(), + [data.query.queryString, queryState.query] + ); + + const relativeTimeRange = useMemo( + () => queryState.time ?? data.query.timefilter.timefilter.getTimeDefaults(), + [data.query.timefilter.timefilter, queryState.time] + ); + + return { filters, query, relativeTimeRange }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx b/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx new file mode 100644 index 0000000000000..26070db1c7e54 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx @@ -0,0 +1,239 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +import { TimeRange } from '@kbn/data-plugin/common'; +import { renderHook } from '@testing-library/react-hooks'; +import { UnifiedHistogramBucketInterval } from '../types'; +import { useTimeRange } from './use_time_range'; + +jest.mock('@kbn/datemath', () => ({ + parse: jest.fn((datetime: string) => { + return { + format: jest.fn(() => { + return datetime; + }), + }; + }), +})); + +describe('useTimeRange', () => { + const uiSettings = uiSettingsServiceMock.createStartContract(); + uiSettings.get.mockReturnValue('dateFormat'); + const bucketInterval: UnifiedHistogramBucketInterval = { + description: '1 minute', + }; + const timeRange: TimeRange = { + from: '2022-11-17T00:00:00.000Z', + to: '2022-11-17T12:00:00.000Z', + }; + const timeInterval = 'auto'; + + it('should return time range text', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute)"` + ); + }); + + it('should return time range text when timeInterval is not auto', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval: '1m', + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: 1 minute)"` + ); + }); + + it('should return time range text when bucketInterval is undefined', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - Loading)"` + ); + }); + + it('should render time range display', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + `); + }); + + it('should render time range display when buckets are too large', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval: { + ...bucketInterval, + scaled: true, + scale: 2, + }, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + + + + + + `); + }); + + it('should render time range display when there are too many buckets', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval: { + ...bucketInterval, + scaled: true, + scale: 0.5, + }, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + + + + + + `); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_time_range.tsx b/src/plugins/unified_histogram/public/chart/use_time_range.tsx new file mode 100644 index 0000000000000..539f32251b832 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_time_range.tsx @@ -0,0 +1,127 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiText, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { i18n } from '@kbn/i18n'; +import React, { useCallback, useMemo } from 'react'; +import dateMath from '@kbn/datemath'; +import type { TimeRange } from '@kbn/data-plugin/common'; +import type { UnifiedHistogramBucketInterval } from '../types'; + +export const useTimeRange = ({ + uiSettings, + bucketInterval, + timeRange: { from, to }, + timeInterval, +}: { + uiSettings: IUiSettingsClient; + bucketInterval?: UnifiedHistogramBucketInterval; + timeRange: TimeRange; + timeInterval?: string; +}) => { + const dateFormat = useMemo(() => uiSettings.get('dateFormat'), [uiSettings]); + + const toMoment = useCallback( + (datetime?: moment.Moment) => { + if (!datetime) { + return ''; + } + if (!dateFormat) { + return String(datetime); + } + return datetime.format(dateFormat); + }, + [dateFormat] + ); + + const timeRangeText = useMemo(() => { + const timeRange = { + from: dateMath.parse(from), + to: dateMath.parse(to, { roundUp: true }), + }; + + const intervalText = i18n.translate('unifiedHistogram.histogramTimeRangeIntervalDescription', { + defaultMessage: '(interval: {value})', + values: { + value: `${ + timeInterval === 'auto' + ? `${i18n.translate('unifiedHistogram.histogramTimeRangeIntervalAuto', { + defaultMessage: 'Auto', + })} - ` + : '' + }${ + bucketInterval?.description ?? + i18n.translate('unifiedHistogram.histogramTimeRangeIntervalLoading', { + defaultMessage: 'Loading', + }) + }`, + }, + }); + + return `${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${intervalText}`; + }, [bucketInterval, from, timeInterval, to, toMoment]); + + const { euiTheme } = useEuiTheme(); + const timeRangeCss = css` + padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; + `; + + let timeRangeDisplay = ( + + {timeRangeText} + + ); + + if (bucketInterval?.scaled) { + const toolTipTitle = i18n.translate('unifiedHistogram.timeIntervalWithValueWarning', { + defaultMessage: 'Warning', + }); + + const toolTipContent = i18n.translate('unifiedHistogram.bucketIntervalTooltip', { + defaultMessage: + 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}.', + values: { + bucketsDescription: + bucketInterval.scale && bucketInterval.scale > 1 + ? i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooLargeBucketsText', { + defaultMessage: 'buckets that are too large', + }) + : i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooManyBucketsText', { + defaultMessage: 'too many buckets', + }), + bucketIntervalDescription: bucketInterval.description, + }, + }); + + const timeRangeWrapperCss = css` + flex-grow: 0; + `; + + timeRangeDisplay = ( + + {timeRangeDisplay} + + + + + ); + } + + return { + timeRangeText, + timeRangeDisplay, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts b/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts new file mode 100644 index 0000000000000..4782df3683fcb --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts @@ -0,0 +1,212 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Filter } from '@kbn/es-query'; +import { UnifiedHistogramFetchStatus } from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { useTotalHits } from './use_total_hits'; +import { useEffect as mockUseEffect } from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { of, throwError } from 'rxjs'; +import { waitFor } from '@testing-library/dom'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { DataViewType, SearchSourceSearchOptions } from '@kbn/data-plugin/common'; + +jest.mock('react-use/lib/useDebounce', () => { + return jest.fn((...args) => { + mockUseEffect(args[0], args[2]); + }); +}); + +describe('useTotalHits', () => { + const getDeps = () => ({ + services: { data: dataPluginMock.createStartContract() } as any, + dataView: dataViewWithTimefieldMock, + lastReloadRequestTime: undefined, + request: undefined, + hits: { + status: UnifiedHistogramFetchStatus.uninitialized, + total: undefined, + }, + chart: { + hidden: true, + timeInterval: 'auto', + }, + chartVisible: false, + breakdown: undefined, + filters: [], + query: { query: '', language: 'kuery' }, + timeRange: { from: 'now-15m', to: 'now' }, + refetchId: 0, + onTotalHitsChange: jest.fn(), + }); + + it('should fetch total hits on first execution', async () => { + const onTotalHitsChange = jest.fn(); + let fetchOptions: SearchSourceSearchOptions | undefined; + const fetchSpy = jest + .spyOn(searchSourceInstanceMock, 'fetch$') + .mockClear() + .mockImplementation((options) => { + fetchOptions = options; + return of({ + isRunning: false, + isPartial: false, + rawResponse: { + hits: { + total: 42, + }, + }, + }) as any; + }); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const data = dataPluginMock.createStartContract(); + const timeRange = { from: 'now-15m', to: 'now' }; + jest + .spyOn(data.query.timefilter.timefilter, 'createFilter') + .mockClear() + .mockReturnValue(timeRange as any); + const query = { query: 'test query', language: 'kuery' }; + const filters: Filter[] = [{ meta: { index: 'test' }, query: { match_all: {} } }]; + const adapter = new RequestAdapter(); + renderHook(() => + useTotalHits({ + ...getDeps(), + services: { data } as any, + request: { + searchSessionId: '123', + adapter, + }, + query, + filters, + timeRange, + onTotalHitsChange, + }) + ); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.loading, undefined); + expect(setFieldSpy).toHaveBeenCalledWith('index', dataViewWithTimefieldMock); + expect(setFieldSpy).toHaveBeenCalledWith('query', query); + expect(setFieldSpy).toHaveBeenCalledWith('size', 0); + expect(setFieldSpy).toHaveBeenCalledWith('trackTotalHits', true); + expect(setFieldSpy).toHaveBeenCalledWith('filter', [...filters, timeRange]); + expect(fetchSpy).toHaveBeenCalled(); + expect(fetchOptions?.inspector?.adapter).toBe(adapter); + expect(fetchOptions?.sessionId).toBe('123'); + expect(fetchOptions?.abortSignal).toBeInstanceOf(AbortSignal); + expect(fetchOptions?.executionContext?.description).toBe('fetch total hits'); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.complete, 42); + }); + }); + + it('should not fetch total hits if chartVisible is true', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + renderHook(() => useTotalHits({ ...getDeps(), chartVisible: true, onTotalHitsChange })); + expect(onTotalHitsChange).toBeCalledTimes(0); + expect(setFieldSpy).not.toHaveBeenCalled(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should not fetch total hits if hits is undefined', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + renderHook(() => useTotalHits({ ...getDeps(), hits: undefined, onTotalHitsChange })); + expect(onTotalHitsChange).toBeCalledTimes(0); + expect(setFieldSpy).not.toHaveBeenCalled(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should not fetch a second time if fetchId is the same', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const options = { ...getDeps(), refetchId: 0, onTotalHitsChange }; + const { rerender } = renderHook(() => useTotalHits(options)); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(setFieldSpy).toHaveBeenCalled(); + expect(fetchSpy).toHaveBeenCalled(); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + }); + rerender(); + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(setFieldSpy).toHaveBeenCalledTimes(5); + expect(fetchSpy).toHaveBeenCalledTimes(1); + }); + + it('should fetch a second time if fetchId is different', async () => { + const abortSpy = jest.spyOn(AbortController.prototype, 'abort').mockClear(); + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const options = { ...getDeps(), refetchId: 0, onTotalHitsChange }; + const { rerender } = renderHook(() => useTotalHits(options)); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(setFieldSpy).toHaveBeenCalled(); + expect(fetchSpy).toHaveBeenCalled(); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + }); + options.refetchId = 1; + rerender(); + expect(abortSpy).toHaveBeenCalled(); + expect(onTotalHitsChange).toBeCalledTimes(3); + expect(setFieldSpy).toHaveBeenCalledTimes(10); + expect(fetchSpy).toHaveBeenCalledTimes(2); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(4); + }); + }); + + it('should call onTotalHitsChange with an error status if fetch fails', async () => { + const onTotalHitsChange = jest.fn(); + const error = new Error('test error'); + jest + .spyOn(searchSourceInstanceMock, 'fetch$') + .mockClear() + .mockReturnValue(throwError(() => error)); + renderHook(() => useTotalHits({ ...getDeps(), onTotalHitsChange })); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.error, error); + }); + }); + + it('should call searchSource.setOverwriteDataViewType if dataView is a rollup', async () => { + const setOverwriteDataViewTypeSpy = jest + .spyOn(searchSourceInstanceMock, 'setOverwriteDataViewType') + .mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const data = dataPluginMock.createStartContract(); + const timeRange = { from: 'now-15m', to: 'now' }; + jest + .spyOn(data.query.timefilter.timefilter, 'createFilter') + .mockClear() + .mockReturnValue(timeRange as any); + const filters: Filter[] = [{ meta: { index: 'test' }, query: { match_all: {} } }]; + renderHook(() => + useTotalHits({ + ...getDeps(), + dataView: { + ...dataViewWithTimefieldMock, + type: DataViewType.ROLLUP, + } as any, + filters, + }) + ); + expect(setOverwriteDataViewTypeSpy).toHaveBeenCalledWith(undefined); + expect(setFieldSpy).toHaveBeenCalledWith('filter', filters); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_total_hits.ts b/src/plugins/unified_histogram/public/chart/use_total_hits.ts new file mode 100644 index 0000000000000..3f24b642c81bf --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_total_hits.ts @@ -0,0 +1,177 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { isCompleteResponse } from '@kbn/data-plugin/public'; +import { DataView, DataViewType } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; +import { MutableRefObject, useRef } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import { catchError, filter, lastValueFrom, map, of } from 'rxjs'; +import { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, + UnifiedHistogramServices, +} from '../types'; +import { REQUEST_DEBOUNCE_MS } from './consts'; + +export const useTotalHits = ({ + services, + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + timeRange, + refetchId, + onTotalHitsChange, +}: { + services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + timeRange: TimeRange; + refetchId: number; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; +}) => { + const abortController = useRef(); + + useDebounce( + () => { + fetchTotalHits({ + services, + abortController, + dataView, + request, + hits, + chartVisible, + filters, + query, + timeRange, + onTotalHitsChange, + }); + }, + REQUEST_DEBOUNCE_MS, + [onTotalHitsChange, refetchId, services] + ); +}; + +const fetchTotalHits = async ({ + services: { data }, + abortController, + dataView, + request, + hits, + chartVisible, + filters: originalFilters, + query, + timeRange, + onTotalHitsChange, +}: { + services: UnifiedHistogramServices; + abortController: MutableRefObject; + dataView: DataView; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chartVisible: boolean; + filters: Filter[]; + query: Query | AggregateQuery; + timeRange: TimeRange; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; +}) => { + abortController.current?.abort(); + abortController.current = undefined; + + // Either the chart is visible, in which case Lens will make the request, + // or there is no hits context, which means the total hits should be hidden + if (chartVisible || !hits) { + return; + } + + onTotalHitsChange?.(UnifiedHistogramFetchStatus.loading, hits.total); + + const searchSource = data.search.searchSource.createEmpty(); + + searchSource + .setField('index', dataView) + .setField('query', query) + .setField('size', 0) + .setField('trackTotalHits', true); + + let filters = originalFilters; + + if (dataView.type === DataViewType.ROLLUP) { + // We treat that data view as "normal" even if it was a rollup data view, + // since the rollup endpoint does not support querying individual documents, but we + // can get them from the regular _search API that will be used if the data view + // not a rollup data view. + searchSource.setOverwriteDataViewType(undefined); + } else { + // Set the date range filter fields from timeFilter using the absolute format. + // Search sessions requires that it be converted from a relative range + const timeFilter = data.query.timefilter.timefilter.createFilter(dataView, timeRange); + + if (timeFilter) { + filters = [...filters, timeFilter]; + } + } + + searchSource.setField('filter', filters); + + abortController.current = new AbortController(); + + // Let the consumer inspect the request if they want to track it + const inspector = request?.adapter + ? { + adapter: request.adapter, + title: i18n.translate('unifiedHistogram.inspectorRequestDataTitleTotalHits', { + defaultMessage: 'Total hits', + }), + description: i18n.translate('unifiedHistogram.inspectorRequestDescriptionTotalHits', { + defaultMessage: 'This request queries Elasticsearch to fetch the total hits.', + }), + } + : undefined; + + const fetch$ = searchSource + .fetch$({ + inspector, + sessionId: request?.searchSessionId, + abortSignal: abortController.current.signal, + executionContext: { + description: 'fetch total hits', + }, + }) + .pipe( + filter((res) => isCompleteResponse(res)), + map((res) => res.rawResponse.hits.total as number), + catchError((error: Error) => of(error)) + ); + + const result = await lastValueFrom(fetch$); + + const resultStatus = + result instanceof Error + ? UnifiedHistogramFetchStatus.error + : UnifiedHistogramFetchStatus.complete; + + onTotalHitsChange?.(resultStatus, result); +}; diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx index d094fef953af8..03b350448e9c2 100644 --- a/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx @@ -13,6 +13,7 @@ import type { HitsCounterProps } from './hits_counter'; import { HitsCounter } from './hits_counter'; import { findTestSubject } from '@elastic/eui/lib/test'; import { EuiLoadingSpinner } from '@elastic/eui'; +import { UnifiedHistogramFetchStatus } from '../types'; describe('hits counter', function () { let props: HitsCounterProps; @@ -21,7 +22,7 @@ describe('hits counter', function () { beforeAll(() => { props = { hits: { - status: 'complete', + status: UnifiedHistogramFetchStatus.complete, total: 2, }, }; @@ -35,7 +36,10 @@ describe('hits counter', function () { it('expect to render 1,899 hits if 1899 hits given', function () { component = mountWithIntl( - + ); const hits = findTestSubject(component, 'unifiedHistogramQueryHits'); expect(hits.text()).toBe('1,899'); @@ -48,12 +52,16 @@ describe('hits counter', function () { }); it('should render a EuiLoadingSpinner when status is partial', () => { - component = mountWithIntl(); + component = mountWithIntl( + + ); expect(component.find(EuiLoadingSpinner).length).toBe(1); }); it('should render unifiedHistogramQueryHitsPartial when status is partial', () => { - component = mountWithIntl(); + component = mountWithIntl( + + ); expect(component.find('[data-test-subj="unifiedHistogramQueryHitsPartial"]').length).toBe(1); }); diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx index 39df40650557c..b6f1212bfeaed 100644 --- a/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx @@ -37,6 +37,9 @@ export function HitsCounter({ hits, append }: HitsCounterProps) { const hitsCounterCss = css` flex-grow: 0; `; + const hitsCounterTextCss = css` + overflow: hidden; + `; return ( - - + + {hits.status === 'partial' && ( new UnifiedHistogramPublicPlugin(); diff --git a/src/plugins/unified_histogram/public/layout/layout.test.tsx b/src/plugins/unified_histogram/public/layout/layout.test.tsx index 3cb3fb254ecf7..d77bbfa05be30 100644 --- a/src/plugins/unified_histogram/public/layout/layout.test.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.test.tsx @@ -6,13 +6,20 @@ * Side Public License, v 1. */ +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { ReactWrapper } from 'enzyme'; import React from 'react'; import { act } from 'react-dom/test-utils'; +import { of } from 'rxjs'; import { Chart } from '../chart'; import { Panels, PANELS_MODE } from '../panels'; -import type { UnifiedHistogramChartContext, UnifiedHistogramHitsContext } from '../types'; +import { + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, +} from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; import { UnifiedHistogramLayout, UnifiedHistogramLayoutProps } from './layout'; @@ -30,19 +37,13 @@ jest.mock('@elastic/eui', () => { describe('Layout', () => { const createHits = (): UnifiedHistogramHitsContext => ({ - status: 'complete', + status: UnifiedHistogramFetchStatus.complete, total: 10, }); const createChart = (): UnifiedHistogramChartContext => ({ - status: 'complete', hidden: false, timeInterval: 'auto', - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, }); const mountComponent = async ({ @@ -59,12 +60,21 @@ describe('Layout', () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); + const component = mountWithIntl( ); diff --git a/src/plugins/unified_histogram/public/layout/layout.tsx b/src/plugins/unified_histogram/public/layout/layout.tsx index 229d8a922e465..87d4170a1035f 100644 --- a/src/plugins/unified_histogram/public/layout/layout.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.tsx @@ -11,17 +11,41 @@ import type { PropsWithChildren, ReactElement, RefObject } from 'react'; import React, { useMemo } from 'react'; import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal'; import { css } from '@emotion/css'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { Chart } from '../chart'; import { Panels, PANELS_MODE } from '../panels'; import type { UnifiedHistogramChartContext, UnifiedHistogramServices, UnifiedHistogramHitsContext, + UnifiedHistogramBreakdownContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramRequestContext, + UnifiedHistogramChartLoadEvent, } from '../types'; export interface UnifiedHistogramLayoutProps extends PropsWithChildren { + /** + * Optional class name to add to the layout container + */ className?: string; + /** + * Required services + */ services: UnifiedHistogramServices; + /** + * The current data view + */ + dataView: DataView; + /** + * Can be updated to `Date.now()` to force a refresh + */ + lastReloadRequestTime?: number; + /** + * Context object for requests made by unified histogram components -- optional + */ + request?: UnifiedHistogramRequestContext; /** * Context object for the hits count -- leave undefined to hide the hits count */ @@ -30,6 +54,10 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * Context object for the chart -- leave undefined to hide the chart */ chart?: UnifiedHistogramChartContext; + /** + * Context object for the breakdown -- leave undefined to hide the breakdown + */ + breakdown?: UnifiedHistogramBreakdownContext; /** * Ref to the element wrapping the layout which will be used for resize calculations */ @@ -49,7 +77,7 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren /** * Callback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button */ - onEditVisualization?: () => void; + onEditVisualization?: (lensAttributes: TypedLensByValueInput['attributes']) => void; /** * Callback to hide or show the chart -- should set {@link UnifiedHistogramChartContext.hidden} to chartHidden */ @@ -58,13 +86,30 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * Callback to update the time interval -- should set {@link UnifiedHistogramChartContext.timeInterval} to timeInterval */ onTimeIntervalChange?: (timeInterval: string) => void; + /** + * Callback to update the breakdown field -- should set {@link UnifiedHistogramBreakdownContext.field} to breakdownField + */ + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; + /** + * Callback to update the total hits -- should set {@link UnifiedHistogramHitsContext.status} to status + * and {@link UnifiedHistogramHitsContext.total} to result + */ + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + /** + * Called when the histogram loading status changes + */ + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } export const UnifiedHistogramLayout = ({ className, services, + dataView, + lastReloadRequestTime, + request, hits, chart, + breakdown, resizeRef, topPanelHeight, appendHitsCounter, @@ -72,6 +117,9 @@ export const UnifiedHistogramLayout = ({ onEditVisualization, onChartHiddenChange, onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, children, }: UnifiedHistogramLayoutProps) => { const topPanelNode = useMemo( @@ -88,7 +136,6 @@ export const UnifiedHistogramLayout = ({ const showFixedPanels = isMobile || !chart || chart.hidden; const { euiTheme } = useEuiTheme(); const defaultTopPanelHeight = euiTheme.base * 12; - const minTopPanelHeight = euiTheme.base * 8; const minMainPanelHeight = euiTheme.base * 10; const chartClassName = @@ -119,14 +166,21 @@ export const UnifiedHistogramLayout = ({ : } onEditVisualization={onEditVisualization} onResetChartHeight={onResetChartHeight} onChartHiddenChange={onChartHiddenChange} onTimeIntervalChange={onTimeIntervalChange} + onBreakdownFieldChange={onBreakdownFieldChange} + onTotalHitsChange={onTotalHitsChange} + onChartLoad={onChartLoad} /> {children} @@ -135,7 +189,7 @@ export const UnifiedHistogramLayout = ({ mode={panelsMode} resizeRef={resizeRef} topPanelHeight={currentTopPanelHeight} - minTopPanelHeight={minTopPanelHeight} + minTopPanelHeight={defaultTopPanelHeight} minMainPanelHeight={minMainPanelHeight} topPanel={} mainPanel={} diff --git a/src/plugins/unified_histogram/public/types.ts b/src/plugins/unified_histogram/public/types.ts index 53f81b0819900..a4b253274abde 100644 --- a/src/plugins/unified_histogram/public/types.ts +++ b/src/plugins/unified_histogram/public/types.ts @@ -10,19 +10,21 @@ import type { Theme } from '@kbn/charts-plugin/public/plugin'; import type { IUiSettingsClient } from '@kbn/core/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import type { Duration, Moment } from 'moment'; -import type { Unit } from '@kbn/datemath'; -import type { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import type { RequestAdapter } from '@kbn/inspector-plugin/public'; +import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; /** * The fetch status of a unified histogram request */ -export type UnifiedHistogramFetchStatus = - | 'uninitialized' - | 'loading' - | 'partial' - | 'complete' - | 'error'; +export enum UnifiedHistogramFetchStatus { + uninitialized = 'uninitialized', + loading = 'loading', + partial = 'partial', + complete = 'complete', + error = 'error', +} /** * The services required by the unified histogram components @@ -32,81 +34,46 @@ export interface UnifiedHistogramServices { theme: Theme; uiSettings: IUiSettingsClient; fieldFormats: FieldFormatsStart; + lens: LensPublicStart; } -interface Column { - id: string; - name: string; -} - -interface Row { - [key: string]: number | 'NaN'; -} - -interface Dimension { - accessor: 0 | 1; - format: SerializedFieldFormat<{ pattern: string }>; - label: string; -} - -interface Ordered { - date: true; - interval: Duration; - intervalESUnit: string; - intervalESValue: number; - min: Moment; - max: Moment; -} - -interface HistogramParams { - date: true; - interval: Duration; - intervalESValue: number; - intervalESUnit: Unit; - format: string; - bounds: HistogramParamsBounds; -} - -export interface HistogramParamsBounds { - min: Moment; - max: Moment; -} - -export interface Table { - columns: Column[]; - rows: Row[]; +/** + * The bucketInterval object returned by {@link buildBucketInterval} + */ +export interface UnifiedHistogramBucketInterval { + scaled?: boolean; + description?: string; + scale?: number; } -export interface Dimensions { - x: Dimension & { params: HistogramParams }; - y: Dimension; -} +export type UnifiedHistogramAdapters = Partial; /** - * The chartData object returned by {@link buildChartData} that - * should be used to set {@link UnifiedHistogramChartContext.data} + * Emitted when the histogram loading status changes */ -export interface UnifiedHistogramChartData { - values: Array<{ - x: number; - y: number; - }>; - xAxisOrderedValues: number[]; - xAxisFormat: Dimension['format']; - yAxisFormat: Dimension['format']; - xAxisLabel: Column['name']; - yAxisLabel?: Column['name']; - ordered: Ordered; +export interface UnifiedHistogramChartLoadEvent { + /** + * True if loading is complete + */ + complete: boolean; + /** + * Inspector adapters for the request + */ + adapters: UnifiedHistogramAdapters; } /** - * The bucketInterval object returned by {@link buildChartData} that - * should be used to set {@link UnifiedHistogramChartContext.bucketInterval} + * Context object for requests made by unified histogram components */ -export interface UnifiedHistogramBucketInterval { - scaled?: boolean; - description?: string; - scale?: number; +export interface UnifiedHistogramRequestContext { + /** + * Current search session ID + */ + searchSessionId?: string; + /** + * The adapter to use for requests (does not apply to Lens requests) + */ + adapter?: RequestAdapter; } /** @@ -116,7 +83,7 @@ export interface UnifiedHistogramHitsContext { /** * The fetch status of the hits count request */ - status: UnifiedHistogramFetchStatus; + status?: UnifiedHistogramFetchStatus; /** * The total number of hits */ @@ -127,10 +94,6 @@ export interface UnifiedHistogramHitsContext { * Context object for the chart */ export interface UnifiedHistogramChartContext { - /** - * The fetch status of the chart request - */ - status: UnifiedHistogramFetchStatus; /** * Controls whether or not the chart is hidden */ @@ -140,15 +103,17 @@ export interface UnifiedHistogramChartContext { */ timeInterval?: string; /** - * The bucketInterval object returned by {@link buildChartData} - */ - bucketInterval?: UnifiedHistogramBucketInterval; - /** - * The chartData object returned by {@link buildChartData} + * The chart title -- sets the title property on the Lens chart input */ - data?: UnifiedHistogramChartData; + title?: string; +} + +/** + * Context object for the histogram breakdown + */ +export interface UnifiedHistogramBreakdownContext { /** - * Error from failed chart request + * The field used for the breakdown */ - error?: Error; + field?: DataViewField; } diff --git a/src/plugins/unified_histogram/tsconfig.json b/src/plugins/unified_histogram/tsconfig.json index a275fdc784dbc..9c6213783980c 100644 --- a/src/plugins/unified_histogram/tsconfig.json +++ b/src/plugins/unified_histogram/tsconfig.json @@ -5,12 +5,13 @@ "emitDeclarationOnly": true, "declaration": true, }, - "include": ["common/**/*", "public/**/*", "server/**/*"], + "include": [ "../../../typings/**/*", "common/**/*", "public/**/*", "server/**/*"], "kbn_references": [ { "path": "../../core/tsconfig.json" }, { "path": "../charts/tsconfig.json" }, { "path": "../data/tsconfig.json" }, { "path": "../data_views/tsconfig.json" }, - { "path": "../saved_search/tsconfig.json" } + { "path": "../saved_search/tsconfig.json" }, + { "path": "../../../x-pack/plugins/lens/tsconfig.json" } ] } diff --git a/test/functional/apps/discover/group1/_discover.ts b/test/functional/apps/discover/group1/_discover.ts index 60f2a54dd01fd..1cba5aa4812d8 100644 --- a/test/functional/apps/discover/group1/_discover.ts +++ b/test/functional/apps/discover/group1/_discover.ts @@ -18,7 +18,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const queryBar = getService('queryBar'); const inspector = getService('inspector'); - const elasticChart = getService('elasticChart'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); @@ -106,48 +105,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); - it('should modify the time range when the histogram is brushed', async function () { - // this is the number of renderings of the histogram needed when new data is fetched - // this needs to be improved - const renderingCountInc = 2; - const prevRenderingCount = await elasticChart.getVisualizationRenderingCount(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await retry.waitFor('chart rendering complete', async () => { - const actualCount = await elasticChart.getVisualizationRenderingCount(); - const expectedCount = prevRenderingCount + renderingCountInc; - log.debug( - `renderings before brushing - actual: ${actualCount} expected: ${expectedCount}` - ); - return actualCount === expectedCount; - }); - let prevRowData = ''; - // to make sure the table is already rendered - await retry.try(async () => { - prevRowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); - }); - - await PageObjects.discover.brushHistogram(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await retry.waitFor('chart rendering complete after being brushed', async () => { - const actualCount = await elasticChart.getVisualizationRenderingCount(); - const expectedCount = prevRenderingCount + renderingCountInc * 2; - log.debug( - `renderings after brushing - actual: ${actualCount} expected: ${expectedCount}` - ); - return actualCount === expectedCount; - }); - const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); - expect(Math.round(newDurationHours)).to.be(26); - - await retry.waitFor('doc table containing the documents of the brushed range', async () => { - const rowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table after brushing: ${rowData}`); - return prevRowData !== rowData; - }); - }); - it('should show correct initial chart interval of Auto', async function () { await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); @@ -265,26 +222,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('empty query', function () { - it('should update the histogram timerange when the query is resubmitted', async function () { - await kibanaServer.uiSettings.update({ - 'timepicker:timeDefaults': '{ "from": "2015-09-18T19:37:13.000Z", "to": "now"}', - }); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.header.awaitKibanaChrome(); - const initialTimeString = await PageObjects.discover.getChartTimespan(); - await queryBar.submitQuery(); - - await retry.waitFor('chart timespan to have changed', async () => { - const refreshedTimeString = await PageObjects.discover.getChartTimespan(); - log.debug( - `Timestamp before: ${initialTimeString}, Timestamp after: ${refreshedTimeString}` - ); - return refreshedTimeString !== initialTimeString; - }); - }); - }); - describe('managing fields', function () { it('should add a field, sort by it, remove it and also sorting by it', async function () { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); diff --git a/test/functional/apps/discover/group1/_discover_histogram.ts b/test/functional/apps/discover/group1/_discover_histogram.ts index 12effb75cb7f3..70a1fba5afafc 100644 --- a/test/functional/apps/discover/group1/_discover_histogram.ts +++ b/test/functional/apps/discover/group1/_discover_histogram.ts @@ -23,6 +23,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const browser = getService('browser'); const retry = getService('retry'); + const log = getService('log'); + const queryBar = getService('queryBar'); describe('discover histogram', function describeIndexTests() { before(async () => { @@ -52,6 +54,69 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } } + it('should modify the time range when the histogram is brushed', async function () { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + // this is the number of renderings of the histogram needed when new data is fetched + let renderingCountInc = 1; + const prevRenderingCount = await elasticChart.getVisualizationRenderingCount(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await retry.waitFor('chart rendering complete', async () => { + const actualCount = await elasticChart.getVisualizationRenderingCount(); + const expectedCount = prevRenderingCount + renderingCountInc; + log.debug(`renderings before brushing - actual: ${actualCount} expected: ${expectedCount}`); + return actualCount === expectedCount; + }); + let prevRowData = ''; + // to make sure the table is already rendered + await retry.try(async () => { + prevRowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); + }); + + await PageObjects.discover.brushHistogram(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + renderingCountInc = 2; + await retry.waitFor('chart rendering complete after being brushed', async () => { + const actualCount = await elasticChart.getVisualizationRenderingCount(); + const expectedCount = prevRenderingCount + renderingCountInc * 2; + log.debug(`renderings after brushing - actual: ${actualCount} expected: ${expectedCount}`); + return actualCount <= expectedCount; + }); + const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); + expect(Math.round(newDurationHours)).to.be(26); + + await retry.waitFor('doc table containing the documents of the brushed range', async () => { + const rowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table after brushing: ${rowData}`); + return prevRowData !== rowData; + }); + }); + + it('should update the histogram timerange when the query is resubmitted', async function () { + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': '{ "from": "2015-09-18T19:37:13.000Z", "to": "now"}', + }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.awaitKibanaChrome(); + const initialTimeString = await PageObjects.discover.getChartTimespan(); + await queryBar.clickQuerySubmitButton(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + await retry.waitFor('chart timespan to have changed', async () => { + const refreshedTimeString = await PageObjects.discover.getChartTimespan(); + await queryBar.clickQuerySubmitButton(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + log.debug( + `Timestamp before: ${initialTimeString}, Timestamp after: ${refreshedTimeString}` + ); + return refreshedTimeString !== initialTimeString; + }); + }); + it('should visualize monthly data with different day intervals', async () => { const from = 'Nov 1, 2017 @ 00:00:00.000'; const to = 'Mar 21, 2018 @ 00:00:00.000'; @@ -83,8 +148,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(true); await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // histogram is hidden, when reloading the page it should remain hidden await browser.refresh(); canvasExists = await elasticChart.canvasExists(); @@ -92,8 +159,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); await PageObjects.header.waitUntilLoadingHasFinished(); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(true); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(true); + }); }); it('should allow hiding the histogram, persisted in saved search', async () => { const from = 'Jan 1, 2010 @ 00:00:00.000'; @@ -104,8 +173,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart for saved search await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - let canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + let canvasExists: boolean; + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // save search await PageObjects.discover.saveSearch(savedSearch); @@ -147,8 +219,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - let canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + let canvasExists: boolean; + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // save search await PageObjects.discover.saveSearch('persisted hidden histogram'); @@ -157,8 +232,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // open chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(true); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(true); + }); // go to dashboard await PageObjects.common.navigateToApp('dashboard'); @@ -173,8 +250,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); }); }); } diff --git a/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts b/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts new file mode 100644 index 0000000000000..805d59aee937d --- /dev/null +++ b/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts @@ -0,0 +1,61 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const filterBar = getService('filterBar'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + + describe('discover unified histogram breakdown', function describeIndexTests() { + before(async () => { + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + }); + + it('should choose breakdown field', async () => { + await PageObjects.discover.chooseBreakdownField('extension.raw'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const list = await PageObjects.discover.getHistogramLegendList(); + expect(list).to.eql(['Other', 'png', 'css', 'jpg']); + }); + + it('should add filter using histogram legend values', async () => { + await PageObjects.discover.clickLegendFilter('png', '+'); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await filterBar.hasFilter('extension.raw', 'png')).to.be(true); + }); + + it('should save breakdown field in saved search', async () => { + await filterBar.removeFilter('extension.raw'); + await PageObjects.discover.saveSearch('with breakdown'); + + await PageObjects.discover.clickNewSearchButton(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const prevList = await PageObjects.discover.getHistogramLegendList(); + expect(prevList).to.eql([]); + + await PageObjects.discover.loadSavedSearch('with breakdown'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const list = await PageObjects.discover.getHistogramLegendList(); + expect(list).to.eql(['Other', 'png', 'css', 'jpg']); + }); + }); +} diff --git a/test/functional/apps/discover/group1/_inspector.ts b/test/functional/apps/discover/group1/_inspector.ts index 10451adc98e4f..851f992f42b20 100644 --- a/test/functional/apps/discover/group1/_inspector.ts +++ b/test/functional/apps/discover/group1/_inspector.ts @@ -38,10 +38,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover.json'); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); // delete .kibana index and update configDoc - await kibanaServer.uiSettings.replace({ - defaultIndex: 'logstash-*', - }); - + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); }); @@ -51,9 +49,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should display request stats with no results', async () => { await inspector.open(); - await testSubjects.click('inspectorRequestChooser'); let foundZero = false; - for (const subj of ['Documents', 'Chart_data']) { + for (const subj of ['Documents', 'Data']) { + await testSubjects.click('inspectorRequestChooser'); await testSubjects.click(`inspectorRequestChooser${subj}`); if (await testSubjects.exists('inspectorRequestDetailStatistics', { timeout: 500 })) { await testSubjects.click(`inspectorRequestDetailStatistics`); diff --git a/test/functional/apps/discover/group1/index.ts b/test/functional/apps/discover/group1/index.ts index ab6798400b7a2..82fd341ccce04 100644 --- a/test/functional/apps/discover/group1/index.ts +++ b/test/functional/apps/discover/group1/index.ts @@ -23,6 +23,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_no_data')); loadTestFile(require.resolve('./_discover')); loadTestFile(require.resolve('./_discover_accessibility')); + loadTestFile(require.resolve('./_discover_histogram_breakdown')); loadTestFile(require.resolve('./_discover_histogram')); loadTestFile(require.resolve('./_doc_accessibility')); loadTestFile(require.resolve('./_filter_editor')); diff --git a/test/functional/apps/discover/group2/_huge_fields.ts b/test/functional/apps/discover/group2/_huge_fields.ts index 085788f1139d0..7ffcc891506e3 100644 --- a/test/functional/apps/discover/group2/_huge_fields.ts +++ b/test/functional/apps/discover/group2/_huge_fields.ts @@ -42,6 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await security.testUser.restoreDefaults(); await esArchiver.unload('test/functional/fixtures/es_archiver/huge_fields'); await kibanaServer.uiSettings.unset('timepicker:timeDefaults'); + await kibanaServer.savedObjects.cleanStandardList(); }); }); } diff --git a/test/functional/apps/discover/group2/_search_on_page_load.ts b/test/functional/apps/discover/group2/_search_on_page_load.ts index 2adeb9606d5f6..cb2b21e3849db 100644 --- a/test/functional/apps/discover/group2/_search_on_page_load.ts +++ b/test/functional/apps/discover/group2/_search_on_page_load.ts @@ -144,7 +144,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('discoverNewButton'); await PageObjects.header.waitUntilLoadingHasFinished(); - await retry.waitFor('number of fetches to be 0', waitForFetches(1)); + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); }); }); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 0b22917be5e49..a7181b9490314 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { FtrService } from '../ftr_provider_context'; +import { WebElementWrapper } from '../services/lib/web_element_wrapper'; type SidebarSectionName = 'meta' | 'empty' | 'available' | 'unmapped' | 'popular' | 'selected'; @@ -27,6 +28,7 @@ export class DiscoverPageObject extends FtrService { private readonly kibanaServer = this.ctx.getService('kibanaServer'); private readonly fieldEditor = this.ctx.getService('fieldEditor'); private readonly queryBar = this.ctx.getService('queryBar'); + private readonly comboBox = this.ctx.getService('comboBox'); private readonly defaultFindTimeout = this.config.get('timeouts.find'); @@ -204,6 +206,22 @@ export class DiscoverPageObject extends FtrService { ); } + public async chooseBreakdownField(field: string) { + await this.comboBox.set('unifiedHistogramBreakdownFieldSelector', field); + } + + public async getHistogramLegendList() { + const unifiedHistogram = await this.testSubjects.find('unifiedHistogramChart'); + const list = await unifiedHistogram.findAllByClassName('echLegendItem__label'); + return Promise.all(list.map((elem: WebElementWrapper) => elem.getVisibleText())); + } + + public async clickLegendFilter(field: string, type: '+' | '-') { + const filterType = type === '+' ? 'filterIn' : 'filterOut'; + await this.testSubjects.click(`legend-${field}`); + await this.testSubjects.click(`legend-${field}-${filterType}`); + } + public async getCurrentQueryName() { return await this.globalNav.getLastBreadcrumb(); } diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index 366f281277c5e..44aec2e3fb187 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -298,7 +298,14 @@ export class TimePickerPageObject extends FtrService { await this.testSubjects.click('superDatePickerToggleRefreshButton'); } - await this.inputValue('superDatePickerRefreshIntervalInput', intervalS.toString()); + await this.retry.waitFor('auto refresh to be set correctly', async () => { + await this.inputValue('superDatePickerRefreshIntervalInput', intervalS.toString()); + return ( + (await this.testSubjects.getAttribute('superDatePickerRefreshIntervalInput', 'value')) === + intervalS.toString() + ); + }); + await this.quickSelectTimeMenuToggle.close(); } diff --git a/x-pack/plugins/data_visualizer/tsconfig.json b/x-pack/plugins/data_visualizer/tsconfig.json index 82484dc83b6cd..f818a547aa2fa 100644 --- a/x-pack/plugins/data_visualizer/tsconfig.json +++ b/x-pack/plugins/data_visualizer/tsconfig.json @@ -28,6 +28,7 @@ { "path": "../../../src/plugins/unified_search/tsconfig.json" }, { "path": "../cloud/tsconfig.json" }, { "path": "../cloud_integrations/cloud_chat/tsconfig.json" }, - { "path": "../../../src/plugins/embeddable/tsconfig.json" } + { "path": "../../../src/plugins/embeddable/tsconfig.json" }, + { "path": "../../../src/plugins/discover/tsconfig.json" } ] } diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 56e1970cc764b..f814c0700d409 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -37,8 +37,7 @@ "taskManager", "globalSearch", "savedObjectsTagging", - "spaces", - "discover" + "spaces" ], "configPath": ["xpack", "lens"], "extraPublicDirs": ["common/constants"], diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx index 2e1b021e21470..582741fe68741 100644 --- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -233,7 +233,7 @@ export const LensTopNavMenu = ({ uiSettings, application, attributeService, - discover, + share, dashboardFeatureFlag, dataViewFieldEditor, dataViewEditor, @@ -424,8 +424,10 @@ export const LensTopNavMenu = ({ currentDoc, ]); + const discoverLocator = share?.url.locators.get('DISCOVER_APP_LOCATOR'); + const layerMetaInfo = useMemo(() => { - if (!activeDatasourceId || !discover) { + if (!activeDatasourceId || !discoverLocator) { return; } return getLayerMetaInfo( @@ -438,7 +440,7 @@ export const LensTopNavMenu = ({ ); }, [ activeDatasourceId, - discover, + discoverLocator, datasourceMap, datasourceStates, activeData, @@ -559,7 +561,7 @@ export const LensTopNavMenu = ({ const { error, meta } = layerMetaInfo; // If Discover is not available, return // If there's no data, return - if (error || !discover || !meta) { + if (error || !discoverLocator || !meta) { return; } const { filters: newFilters, query: newQuery } = combineQueryAndFilters( @@ -570,7 +572,7 @@ export const LensTopNavMenu = ({ getEsQueryConfig(uiSettings) ); - return discover.locator!.getRedirectUrl({ + return discoverLocator.getRedirectUrl({ dataViewSpec: dataViews.indexPatterns[meta.id]?.spec, timeRange: data.query.timefilter.timefilter.getTime(), filters: newFilters, @@ -611,7 +613,7 @@ export const LensTopNavMenu = ({ setIsSaveModalVisible, goBackToOriginatingApp, redirectToOrigin, - discover, + discoverLocator, query, filters, indexPatterns, diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index ef1933dbd5ca1..82873673271c6 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -67,7 +67,7 @@ export async function getLensServices( usageCollection, fieldFormats, spaces, - discover, + share, unifiedSearch, } = startDependencies; @@ -108,7 +108,7 @@ export async function getLensServices( // Temporarily required until the 'by value' paradigm is default. dashboardFeatureFlag: startDependencies.dashboard.dashboardFeatureFlagConfig, spaces, - discover, + share, unifiedSearch, docLinks: coreStart.docLinks, }; diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts index b2466c60e6e4e..831b7ce54da39 100644 --- a/x-pack/plugins/lens/public/app_plugin/types.ts +++ b/x-pack/plugins/lens/public/app_plugin/types.ts @@ -7,7 +7,6 @@ import type { History } from 'history'; import type { OnSaveProps } from '@kbn/saved-objects-plugin/public'; -import { DiscoverStart } from '@kbn/discover-plugin/public'; import { Observable } from 'rxjs'; import { SpacesApi } from '@kbn/spaces-plugin/public'; import type { @@ -44,6 +43,7 @@ import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { DocLinksStart } from '@kbn/core-doc-links-browser'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { DatasourceMap, EditorFrameInstance, @@ -153,7 +153,7 @@ export interface LensAppServices { presentationUtil: PresentationUtilPluginStart; spaces: SpacesApi; charts: ChartsPluginSetup; - discover?: DiscoverStart; + share?: SharePluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; docLinks: DocLinksStart; // Temporarily required until the 'by value' paradigm is default. diff --git a/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx index a0514dafd61b0..4d7064647eca3 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx @@ -9,7 +9,6 @@ import React, { ReactElement } from 'react'; import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { EuiLoadingSpinner, EuiPopover } from '@elastic/eui'; -import type { DiscoverStart } from '@kbn/discover-plugin/public'; import { InnerFieldItem, FieldItemProps } from './field_item'; import { coreMock } from '@kbn/core/public/mocks'; import { mountWithIntl } from '@kbn/test-jest-helpers'; @@ -49,11 +48,15 @@ const mockedServices = { fieldFormats: fieldFormatsServiceMock.createStartContract(), charts: chartPluginMock.createSetupContract(), uiSettings: coreMock.createStart().uiSettings, - discover: { - locator: { - getRedirectUrl: jest.fn(() => 'discover_url'), + share: { + url: { + locators: { + get: jest.fn().mockReturnValue({ + getRedirectUrl: jest.fn(() => 'discover_url'), + }), + }, }, - } as unknown as DiscoverStart, + }, application: { capabilities: { discover: { save: true, saveQuery: true, show: true }, diff --git a/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx b/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx index b77f9db710779..ff118afc84e32 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx @@ -309,10 +309,11 @@ function FieldItemPopoverContents( [indexPattern], getEsQueryConfig(services.uiSettings) ); - if (!services.discover || !services.application.capabilities.discover.show) { + const discoverLocator = services.share?.url.locators.get('DISCOVER_APP_LOCATOR'); + if (!discoverLocator || !services.application.capabilities.discover.show) { return; } - return services.discover.locator!.getRedirectUrl({ + return discoverLocator.getRedirectUrl({ dataViewSpec: indexPattern?.spec, timeRange: services.data.query.timefilter.timefilter.getTime(), filters: newFilters, diff --git a/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx index 54d691073f0ab..18572222a6c8e 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx @@ -11,7 +11,6 @@ import { I18nProvider } from '@kbn/i18n-react'; import type { CoreStart, SavedObjectReference } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { TimeRange } from '@kbn/es-query'; -import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { flatten, isEqual } from 'lodash'; @@ -25,6 +24,7 @@ import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { EuiCallOut, EuiLink } from '@elastic/eui'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { DatasourceDimensionEditorProps, DatasourceDimensionTriggerProps, @@ -143,7 +143,7 @@ export function getFormBasedDatasource({ storage, data, unifiedSearch, - discover, + share, dataViews, fieldFormats, charts, @@ -154,7 +154,7 @@ export function getFormBasedDatasource({ storage: IStorageWrapper; data: DataPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; - discover?: DiscoverStart; + share?: SharePluginStart; dataViews: DataViewsPublicPluginStart; fieldFormats: FieldFormatsStart; charts: ChartsPluginSetup; @@ -434,7 +434,7 @@ export function getFormBasedDatasource({ fieldFormats, charts, unifiedSearch, - discover, + share, }} > @@ -460,7 +460,7 @@ export function getFormBasedDatasource({ fieldFormats, charts, unifiedSearch, - discover, + share, }} > { visualizationType: 'testVis', }; - const createEmbeddable = (noPadding?: boolean) => { + const createEmbeddable = (displayOptions?: { noPadding: boolean }, noPadding?: boolean) => { return new Embeddable( { timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, @@ -1451,9 +1451,7 @@ describe('embeddable', () => { theme: themeServiceMock.createStartContract(), visualizationMap: { [visDocument.visualizationType as string]: { - getDisplayOptions: () => ({ - noPadding: false, - }), + getDisplayOptions: displayOptions ? () => displayOptions : undefined, } as unknown as Visualization, }, datasourceMap: {}, @@ -1481,6 +1479,7 @@ describe('embeddable', () => { ); }; + // no display options and no override let embeddable = createEmbeddable(); embeddable.render(mountpoint); @@ -1490,7 +1489,8 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(1); expect(expressionRenderer.mock.calls[0][0]!.padding).toBe('s'); - embeddable = createEmbeddable(true); + // display options and no override + embeddable = createEmbeddable({ noPadding: true }); embeddable.render(mountpoint); // wait one tick to give embeddable time to initialize @@ -1498,5 +1498,25 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(2); expect(expressionRenderer.mock.calls[1][0]!.padding).toBe(undefined); + + // no display options and override + embeddable = createEmbeddable(undefined, true); + embeddable.render(mountpoint); + + // wait one tick to give embeddable time to initialize + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(expressionRenderer).toHaveBeenCalledTimes(3); + expect(expressionRenderer.mock.calls[1][0]!.padding).toBe(undefined); + + // display options and override + embeddable = createEmbeddable({ noPadding: false }, true); + embeddable.render(mountpoint); + + // wait one tick to give embeddable time to initialize + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(expressionRenderer).toHaveBeenCalledTimes(4); + expect(expressionRenderer.mock.calls[1][0]!.padding).toBe(undefined); }); }); diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 5c75f76a39ac7..2da02bb722b3f 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -729,7 +729,7 @@ export class Embeddable this.updateOutput({ error: new Error(message) }); this.logError('runtime'); }} - noPadding={this.visDisplayOptions?.noPadding} + noPadding={this.visDisplayOptions.noPadding} />
this.dataViewsService!, - hasDiscoverAccess: () => this.hasDiscoverAccess, - application: () => startServices().core.application, - }) - ); - } + + uiActionsEnhanced.registerDrilldown( + new OpenInDiscoverDrilldown({ + dataViews: () => this.dataViewsService!, + locator: () => share?.url.locators.get('DISCOVER_APP_LOCATOR'), + hasDiscoverAccess: () => this.hasDiscoverAccess, + application: () => startServices().core.application, + }) + ); setupExpressions( expressions, @@ -512,14 +511,17 @@ export class LensPlugin { visualizeAggBasedVisAction(core.application) ); - startDependencies.uiActions.addTriggerAction( - CONTEXT_MENU_TRIGGER, - createOpenInDiscoverAction( - startDependencies.discover!, - startDependencies.dataViews!, - this.hasDiscoverAccess - ) - ); + const discoverLocator = startDependencies.share?.url.locators.get('DISCOVER_APP_LOCATOR'); + if (discoverLocator) { + startDependencies.uiActions.addTriggerAction( + CONTEXT_MENU_TRIGGER, + createOpenInDiscoverAction( + discoverLocator, + startDependencies.dataViews, + this.hasDiscoverAccess + ) + ); + } return { EmbeddableComponent: getEmbeddableComponent(core, startDependencies), diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.test.ts b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.test.ts index f9b4cd1a9f0e4..8a3b8d60629cf 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.test.ts +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.test.ts @@ -6,12 +6,12 @@ */ import { DataViewsService } from '@kbn/data-views-plugin/public'; -import { DiscoverStart } from '@kbn/discover-plugin/public'; import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; import { DOC_TYPE } from '../../common'; import { Embeddable } from '../embeddable'; import { createOpenInDiscoverAction } from './open_in_discover_action'; +import type { DiscoverAppLocator } from './open_in_discover_helpers'; describe('open in discover action', () => { describe('compatibility check', () => { @@ -19,7 +19,7 @@ describe('open in discover action', () => { const embeddable = { type: 'NOT_LENS' } as IEmbeddable; const isCompatible = await createOpenInDiscoverAction( - {} as DiscoverStart, + {} as DiscoverAppLocator, {} as DataViewsService, true ).isCompatible({ @@ -37,7 +37,7 @@ describe('open in discover action', () => { // make sure it would work if we had access to Discover expect( await createOpenInDiscoverAction( - {} as DiscoverStart, + {} as DiscoverAppLocator, {} as DataViewsService, hasDiscoverAccess ).isCompatible({ @@ -49,7 +49,7 @@ describe('open in discover action', () => { hasDiscoverAccess = false; expect( await createOpenInDiscoverAction( - {} as DiscoverStart, + {} as DiscoverAppLocator, {} as DataViewsService, hasDiscoverAccess ).isCompatible({ @@ -65,7 +65,7 @@ describe('open in discover action', () => { embeddable.canViewUnderlyingData = jest.fn(() => Promise.resolve(false)); expect( await createOpenInDiscoverAction( - {} as DiscoverStart, + {} as DiscoverAppLocator, {} as DataViewsService, true ).isCompatible({ @@ -79,7 +79,7 @@ describe('open in discover action', () => { embeddable.canViewUnderlyingData = jest.fn(() => Promise.resolve(true)); expect( await createOpenInDiscoverAction( - {} as DiscoverStart, + {} as DiscoverAppLocator, {} as DataViewsService, true ).isCompatible({ @@ -106,16 +106,14 @@ describe('open in discover action', () => { }; const discoverUrl = 'https://discover-redirect-url'; - const discover = { - locator: { - getRedirectUrl: jest.fn(() => discoverUrl), - }, - } as unknown as DiscoverStart; + const locator = { + getRedirectUrl: jest.fn(() => discoverUrl), + } as unknown as DiscoverAppLocator; globalThis.open = jest.fn(); await createOpenInDiscoverAction( - discover, + locator, { get: () => ({ isTimeBased: () => true }) } as unknown as DataViewsService, true ).execute({ @@ -125,7 +123,7 @@ describe('open in discover action', () => { }>); expect(embeddable.getViewUnderlyingDataArgs).toHaveBeenCalled(); - expect(discover.locator!.getRedirectUrl).toHaveBeenCalledWith(viewUnderlyingDataArgs); + expect(locator.getRedirectUrl).toHaveBeenCalledWith(viewUnderlyingDataArgs); expect(globalThis.open).toHaveBeenCalledWith(discoverUrl, '_blank'); }); }); diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts index 45494c5e14b68..7fc04d84f5e15 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import { createAction } from '@kbn/ui-actions-plugin/public'; -import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; import type { DataViewsService } from '@kbn/data-views-plugin/public'; +import type { DiscoverAppLocator } from './open_in_discover_helpers'; const ACTION_OPEN_IN_DISCOVER = 'ACTION_OPEN_IN_DISCOVER'; @@ -20,7 +20,7 @@ interface Context { export const getDiscoverHelpersAsync = async () => await import('../async_services'); export const createOpenInDiscoverAction = ( - discover: Pick, + locator: DiscoverAppLocator, dataViews: Pick, hasDiscoverAccess: boolean ) => @@ -36,7 +36,7 @@ export const createOpenInDiscoverAction = ( getHref: async (context: Context) => { const { getHref } = await getDiscoverHelpersAsync(); return getHref({ - discover, + locator, dataViews, hasDiscoverAccess, ...context, @@ -46,13 +46,13 @@ export const createOpenInDiscoverAction = ( const { isCompatible } = await getDiscoverHelpersAsync(); return isCompatible({ hasDiscoverAccess, - discover, + locator, dataViews, embeddable: context.embeddable, }); }, execute: async (context: Context) => { const { execute } = await getDiscoverHelpersAsync(); - return execute({ ...context, discover, dataViews, hasDiscoverAccess }); + return execute({ ...context, locator, dataViews, hasDiscoverAccess }); }, }); diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx index c4e8fe050df23..bfa0036c14550 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx @@ -7,9 +7,8 @@ import React, { FormEvent } from 'react'; import { IEmbeddable, EmbeddableInput } from '@kbn/embeddable-plugin/public'; -import { DiscoverSetup } from '@kbn/discover-plugin/public'; import type { ApplicationStart } from '@kbn/core/public'; -import { getHref, isCompatible } from './open_in_discover_helpers'; +import { DiscoverAppLocator, getHref, isCompatible } from './open_in_discover_helpers'; import { mount } from 'enzyme'; import { Filter } from '@kbn/es-query'; import { @@ -35,7 +34,7 @@ describe('open in discover drilldown', () => { beforeEach(() => { drilldown = new OpenInDiscoverDrilldown({ - discover: {} as DiscoverSetup, + locator: () => ({} as DiscoverAppLocator), dataViews: () => ({} as DataViewsService), hasDiscoverAccess: () => true, application: () => ({} as ApplicationStart), diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx index 2022e97fb9b45..d9d9a1f4ed955 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx @@ -13,16 +13,16 @@ import type { ApplicationStart } from '@kbn/core/public'; import type { SerializableRecord } from '@kbn/utility-types'; import type { CollectConfigProps as CollectConfigPropsBase } from '@kbn/kibana-utils-plugin/public'; import { reactToUiComponent } from '@kbn/kibana-react-plugin/public'; -import { +import type { UiActionsEnhancedDrilldownDefinition as Drilldown, UiActionsEnhancedBaseActionFactoryContext as BaseActionFactoryContext, } from '@kbn/ui-actions-enhanced-plugin/public'; import { EuiFormRow, EuiSwitch } from '@elastic/eui'; -import type { DiscoverSetup } from '@kbn/discover-plugin/public'; import type { ApplyGlobalFilterActionContext } from '@kbn/unified-search-plugin/public'; import { i18n } from '@kbn/i18n'; import type { DataViewsService } from '@kbn/data-views-plugin/public'; import { DOC_TYPE } from '../../common/constants'; +import type { DiscoverAppLocator } from './open_in_discover_helpers'; interface EmbeddableQueryInput extends EmbeddableInput { query?: Query; @@ -36,7 +36,7 @@ export const getDiscoverHelpersAsync = async () => await import('../async_servic export type EmbeddableWithQueryInput = IEmbeddable; interface UrlDrilldownDeps { - discover: Pick; + locator: () => DiscoverAppLocator | undefined; dataViews: () => Pick; hasDiscoverAccess: () => boolean; application: () => ApplicationStart; @@ -106,7 +106,7 @@ export class OpenInDiscoverDrilldown const { isCompatible } = await getDiscoverHelpersAsync(); return isCompatible({ - discover: this.deps.discover, + locator: this.deps.locator(), dataViews: this.deps.dataViews(), hasDiscoverAccess: this.deps.hasDiscoverAccess(), ...context, @@ -122,7 +122,7 @@ export class OpenInDiscoverDrilldown const { getHref } = await getDiscoverHelpersAsync(); return getHref({ - discover: this.deps.discover, + locator: this.deps.locator(), dataViews: this.deps.dataViews(), hasDiscoverAccess: this.deps.hasDiscoverAccess(), ...context, @@ -137,7 +137,7 @@ export class OpenInDiscoverDrilldown const { getLocation } = await getDiscoverHelpersAsync(); const { app, path, state } = await getLocation({ - discover: this.deps.discover, + locator: this.deps.locator(), dataViews: this.deps.dataViews(), hasDiscoverAccess: this.deps.hasDiscoverAccess(), ...context, diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_helpers.ts b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_helpers.ts index 677a7a4734b2e..7342b82109be9 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_helpers.ts +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_helpers.ts @@ -5,20 +5,31 @@ * 2.0. */ -import type { DiscoverSetup } from '@kbn/discover-plugin/public'; -import { Filter } from '@kbn/es-query'; -import { IEmbeddable } from '@kbn/embeddable-plugin/public'; -import { DataViewsService } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; +import type { DataViewsService } from '@kbn/data-views-plugin/public'; +import type { LocatorPublic } from '@kbn/share-plugin/public'; +import type { SerializableRecord } from '@kbn/utility-types'; import type { Embeddable } from '../embeddable'; import { DOC_TYPE } from '../../common'; +interface DiscoverAppLocatorParams extends SerializableRecord { + timeRange?: TimeRange; + filters?: Filter[]; + indexPatternId?: string; + query?: Query | AggregateQuery | undefined; + columns?: string[]; +} + +export type DiscoverAppLocator = LocatorPublic; + interface Context { embeddable: IEmbeddable; filters?: Filter[]; openInSameTab?: boolean; hasDiscoverAccess: boolean; dataViews: Pick; - discover: Pick; + locator?: DiscoverAppLocator; timeFieldName?: string; } @@ -73,13 +84,7 @@ async function getDiscoverLocationParams({ }; } -export async function getHref({ - embeddable, - discover, - filters, - dataViews, - timeFieldName, -}: Context) { +export async function getHref({ embeddable, locator, filters, dataViews, timeFieldName }: Context) { const params = await getDiscoverLocationParams({ embeddable, filters, @@ -87,14 +92,14 @@ export async function getHref({ timeFieldName, }); - const discoverUrl = discover.locator?.getRedirectUrl(params); + const discoverUrl = locator?.getRedirectUrl(params); return discoverUrl; } export async function getLocation({ embeddable, - discover, + locator, filters, dataViews, timeFieldName, @@ -106,7 +111,7 @@ export async function getLocation({ timeFieldName, }); - const discoverLocation = discover.locator?.getLocation(params); + const discoverLocation = locator?.getLocation(params); if (!discoverLocation) { throw new Error('Discover location not found'); @@ -117,7 +122,7 @@ export async function getLocation({ export async function execute({ embeddable, - discover, + locator, filters, openInSameTab, dataViews, @@ -126,7 +131,7 @@ export async function execute({ }: Context) { const discoverUrl = await getHref({ embeddable, - discover, + locator, filters, dataViews, timeFieldName, diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json index 4f9d89cd2b3cd..4c052e8c9ecaf 100644 --- a/x-pack/plugins/observability/tsconfig.json +++ b/x-pack/plugins/observability/tsconfig.json @@ -30,5 +30,6 @@ { "path": "../translations/tsconfig.json" }, { "path": "../../../src/plugins/unified_search/tsconfig.json"}, { "path": "../../../src/plugins/guided_onboarding/tsconfig.json"}, + { "path": "../../../src/plugins/discover/tsconfig.json" } ] } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 0fb5e576cfb27..f5fac7b6b4459 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2214,12 +2214,8 @@ "discover.grid.viewDoc": "Afficher/Masquer les détails de la boîte de dialogue", "discover.gridSampleSize.advancedSettingsLinkLabel": "Paramètres avancés", "discover.helpMenu.appName": "Découverte", - "discover.inspectorRequestDataTitleChart": "Données du graphique", "discover.inspectorRequestDataTitleDocuments": "Documents", - "discover.inspectorRequestDataTitleTotalHits": "Nombre total de résultats", - "discover.inspectorRequestDescriptionChart": "Cette requête interroge Elasticsearch afin de récupérer les données d'agrégation pour le graphique.", "discover.inspectorRequestDescriptionDocument": "Cette requête interroge Elasticsearch afin de récupérer les documents.", - "discover.inspectorRequestDescriptionTotalHits": "Cette requête interroge Elasticsearch afin de récupérer le nombre total de résultats.", "discover.json.codeEditorAriaLabel": "Affichage JSON en lecture seule d’un document Elasticsearch", "discover.json.copyToClipboardLabel": "Copier dans le presse-papiers", "discover.loadingDocuments": "Chargement des documents", @@ -2267,7 +2263,6 @@ "discover.sampleData.viewLinkLabel": "Découverte", "discover.savedSearch.savedObjectName": "Recherche enregistrée", "discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "Ouvrir dans Discover", - "discover.searchingTitle": "Recherche", "discover.selectColumnHeader": "Sélectionner la colonne", "discover.showAllDocuments": "Afficher tous les documents", "discover.showErrorMessageAgain": "Afficher le message d'erreur", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9f34753a45325..26cb9a3bc6f06 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2210,12 +2210,8 @@ "discover.grid.viewDoc": "詳細ダイアログを切り替え", "discover.gridSampleSize.advancedSettingsLinkLabel": "高度な設定", "discover.helpMenu.appName": "Discover", - "discover.inspectorRequestDataTitleChart": "グラフデータ", "discover.inspectorRequestDataTitleDocuments": "ドキュメント", - "discover.inspectorRequestDataTitleTotalHits": "総ヒット数", - "discover.inspectorRequestDescriptionChart": "このリクエストはElasticsearchにクエリをかけ、グラフの集計データを取得します。", "discover.inspectorRequestDescriptionDocument": "このリクエストはElasticsearchにクエリをかけ、ドキュメントを取得します。", - "discover.inspectorRequestDescriptionTotalHits": "このリクエストはElasticsearchにクエリをかけ、合計一致数を取得します。", "discover.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", "discover.json.copyToClipboardLabel": "クリップボードにコピー", "discover.loadingDocuments": "ドキュメントを読み込み中", @@ -2263,7 +2259,6 @@ "discover.sampleData.viewLinkLabel": "Discover", "discover.savedSearch.savedObjectName": "保存検索", "discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "Discoverで開く", - "discover.searchingTitle": "検索中", "discover.selectColumnHeader": "列を選択", "discover.showAllDocuments": "すべてのドキュメントを表示", "discover.showErrorMessageAgain": "エラーメッセージを表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 7fb9a4c15bb9f..b184a4daf8113 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2214,12 +2214,8 @@ "discover.grid.viewDoc": "切换具有详情的对话框", "discover.gridSampleSize.advancedSettingsLinkLabel": "高级设置", "discover.helpMenu.appName": "Discover", - "discover.inspectorRequestDataTitleChart": "图表数据", "discover.inspectorRequestDataTitleDocuments": "文档", - "discover.inspectorRequestDataTitleTotalHits": "总命中数", - "discover.inspectorRequestDescriptionChart": "此请求将查询 Elasticsearch 以获取图表的聚合数据。", "discover.inspectorRequestDescriptionDocument": "此请求将查询 Elasticsearch 以获取文档。", - "discover.inspectorRequestDescriptionTotalHits": "此请求将查询 Elasticsearch 以获取总命中数。", "discover.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", "discover.json.copyToClipboardLabel": "复制到剪贴板", "discover.loadingDocuments": "正在加载文档", @@ -2267,7 +2263,6 @@ "discover.sampleData.viewLinkLabel": "Discover", "discover.savedSearch.savedObjectName": "已保存搜索", "discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "在 Discover 中打开", - "discover.searchingTitle": "正在搜索", "discover.selectColumnHeader": "选择列", "discover.showAllDocuments": "显示所有文档", "discover.showErrorMessageAgain": "显示错误消息", diff --git a/x-pack/test/functional/apps/discover/visualize_field.ts b/x-pack/test/functional/apps/discover/visualize_field.ts index 453c3467c923a..8c3ebd7fd06a2 100644 --- a/x-pack/test/functional/apps/discover/visualize_field.ts +++ b/x-pack/test/functional/apps/discover/visualize_field.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -91,6 +92,27 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await queryBar.getQueryString()).to.equal('machine.os : ios'); }); + it('should visualize correctly using breakdown field', async () => { + await PageObjects.discover.chooseBreakdownField('extension.raw'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('unifiedHistogramEditVisualization'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await retry.try(async () => { + const breakdownLabel = await testSubjects.find( + 'lnsDragDrop_draggable-Top 3 values of extension.raw' + ); + + const lnsWorkspace = await testSubjects.find('lnsWorkspace'); + const list = await lnsWorkspace.findAllByClassName('echLegendItem__label'); + const values = await Promise.all( + list.map((elem: WebElementWrapper) => elem.getVisibleText()) + ); + + expect(await breakdownLabel.getVisibleText()).to.eql('Top 3 values of extension.raw'); + expect(values).to.eql(['Other', 'png', 'css', 'jpg']); + }); + }); + it('should visualize correctly using adhoc data view', async () => { await PageObjects.discover.createAdHocDataView('logst', true); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts index 29f684c1ebf37..5c73e6ca7c288 100644 --- a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts @@ -175,7 +175,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('unifiedHistogramChart'); - // check the query expect(await queryBar.getQueryString()).be.eql( '( ( bytes > 4000 ) AND ( ( extension.raw: "css" ) OR ( extension.raw: "gif" ) OR ( extension.raw: "jpg" ) ) )' diff --git a/x-pack/test/functional/apps/transform/creation_index_pattern.ts b/x-pack/test/functional/apps/transform/creation_index_pattern.ts index 4dee8e3af8262..5c240b2c0403c 100644 --- a/x-pack/test/functional/apps/transform/creation_index_pattern.ts +++ b/x-pack/test/functional/apps/transform/creation_index_pattern.ts @@ -16,10 +16,11 @@ import { PivotTransformTestData, } from '.'; -export default function ({ getService }: FtrProviderContext) { +export default function ({ getService, getPageObjects }: FtrProviderContext) { const canvasElement = getService('canvasElement'); const esArchiver = getService('esArchiver'); const transform = getService('transform'); + const PageObjects = getPageObjects(['discover']); describe('creation_index_pattern', function () { before(async () => { @@ -698,6 +699,7 @@ export default function ({ getService }: FtrProviderContext) { await transform.testExecution.logTestStep('should navigate to discover'); await transform.table.clickTransformRowAction(testData.transformId, 'Discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); if (testData.discoverAdjustSuperDatePicker) { await transform.discover.assertNoResults(testData.destinationIndex); From e76171cb9865a731810014d22febb6f42ead8c9a Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Mon, 5 Dec 2022 09:02:07 -0500 Subject: [PATCH 09/40] [Fleet] bundled packages - use package storage v2 for synthetics (#146931) ## Summary Relates to failures seen on https://github.com/elastic/kibana/pull/146823 Synthetics package is just published into package storage v2, so it requires to add an exception as it was done for the APM package. --- src/dev/build/tasks/bundle_fleet_packages.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dev/build/tasks/bundle_fleet_packages.ts b/src/dev/build/tasks/bundle_fleet_packages.ts index 9d27b3d9ecc10..f7fe9ffc76573 100644 --- a/src/dev/build/tasks/bundle_fleet_packages.ts +++ b/src/dev/build/tasks/bundle_fleet_packages.ts @@ -70,8 +70,12 @@ export const BundleFleetPackages: Task = { const archivePath = `${fleetPackage.name}-${versionToWrite}.zip`; let archiveUrl = `${eprUrl}/epr/${fleetPackage.name}/${fleetPackage.name}-${fleetPackage.version}.zip`; - // Point APM and Endpoint packages to package storage v2 - if (fleetPackage.name === 'apm' || fleetPackage.name === 'endpoint') { + // Point APM, Endpoint and Synthetics packages to package storage v2 + if ( + fleetPackage.name === 'apm' || + fleetPackage.name === 'endpoint' || + fleetPackage.name === 'synthetics' + ) { archiveUrl = `${PACKAGE_STORAGE_V2_URL}/epr/${fleetPackage.name}/${fleetPackage.name}-${fleetPackage.version}.zip`; } From 4f7685484d7e7f33b8e124b93b271e06961848e8 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Mon, 5 Dec 2022 14:47:57 +0000 Subject: [PATCH 10/40] Fix user authentication area chart (#146783) ## Summary Original issue: https://github.com/elastic/kibana/issues/131791 Before: No area chart displayed for user authentications: Screenshot 2022-12-01 at 13 02 17 Screenshot 2022-12-01 at 12 55 42 Most of the data of area charts look like: ``` [ { "key_as_string": "2022-12-01T00:00:00.000Z", "key": 1669852800000, // x "doc_count": 12, "count": { "value": 0 // y } } ] ``` but user authentications' data looks like: ``` [ { "key_as_string": "2022-12-01T00:00:00.000Z", "key": 1669852800000, // x "doc_count": 12, "count": { "doc_count": 0 // y } } ] ``` The parser (formatGeneralHistogramData) picked up only count.value and ignored count.doc_count. Therefore y value for user authentication was not picked up and no data for rendering the area chart. After: User authentication area chart should be displayed properly. Screenshot 2022-12-01 at 13 07 21 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../common/search_strategy/common/index.ts | 17 ++++++ .../hosts/kpi/common/index.ts | 11 ---- .../users/kpi/authentications/index.ts | 4 +- .../users/kpi/common/index.ts | 13 ----- .../security_solution/users/kpi/index.ts | 1 - .../users/kpi/total_users/index.ts | 3 +- .../format_general_histogram_data.test.ts | 57 +++++++++++++++++++ .../format_general_histogram_data.ts} | 16 +++--- .../factory/hosts/kpi/hosts/index.ts | 2 +- .../factory/hosts/kpi/index.ts | 1 - .../factory/hosts/kpi/unique_ips/index.ts | 2 +- .../users/kpi/authentications/index.ts | 2 +- .../factory/users/kpi/total_users/index.ts | 2 +- 13 files changed, 89 insertions(+), 42 deletions(-) delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/common/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts rename x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/{hosts/kpi/common/index.ts => common/format_general_histogram_data.ts} (54%) diff --git a/x-pack/plugins/security_solution/common/search_strategy/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/common/index.ts index c33c3f9abae6b..851ffaeba2227 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/common/index.ts @@ -19,6 +19,23 @@ export type Maybe = T | null; export type SearchHit = IEsSearchResponse['rawResponse']['hits']['hits'][0]; +export interface KpiHistogramData { + x?: Maybe; + y?: Maybe; +} + +export interface KpiHistogram { + key_as_string: string; + key: number; + doc_count: number; + count: T; +} + +export interface KpiGeneralHistogramCount { + value?: number; + doc_count?: number; +} + export interface PageInfoPaginated { activePage: number; fakeTotalCount: number; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts index dd4e3b1bef58f..7a13e661e914e 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts @@ -11,14 +11,3 @@ export interface HostsKpiHistogramData { x?: Maybe; y?: Maybe; } - -export interface HostsKpiHistogram { - key_as_string: string; - key: number; - doc_count: number; - count: T; -} - -export interface HostsKpiGeneralHistogramCount { - value: number; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts index 27bd722ce14dc..84090bb7ab49f 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts @@ -6,8 +6,8 @@ */ import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; -import type { KpiHistogramData, RequestBasicOptions } from '../../..'; +import type { Inspect, KpiHistogramData, Maybe } from '../../../../common'; +import type { RequestBasicOptions } from '../../..'; export type UsersKpiAuthenticationsRequestOptions = RequestBasicOptions; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/common/index.ts deleted file mode 100644 index a151b39fe95aa..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/common/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 type { Maybe } from '../../../..'; - -export interface KpiHistogramData { - x?: Maybe; - y?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts index bc735313a7314..c89414639b417 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export * from './common'; export * from './total_users'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts index b493685244ee4..5fffe4ebe40c7 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts @@ -6,9 +6,8 @@ */ import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; +import type { Inspect, KpiHistogramData, Maybe } from '../../../../common'; import type { RequestBasicOptions } from '../../..'; -import type { KpiHistogramData } from '../common'; export type TotalUsersKpiRequestOptions = RequestBasicOptions; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts new file mode 100644 index 0000000000000..a646a73079704 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts @@ -0,0 +1,57 @@ +/* + * 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 type { KpiGeneralHistogramCount, KpiHistogram } from '../../../../../common/search_strategy'; +import { formatGeneralHistogramData } from './format_general_histogram_data'; + +describe('formatGeneralHistogramData', () => { + test('Picks up data from count.value', () => { + const mockHistogramData = [ + { + key_as_string: '2022-12-01T00:00:00.000Z', + key: 1669852800000, + doc_count: 4, + count: { + doc_count: 4, + }, + } as KpiHistogram, + ]; + const result = formatGeneralHistogramData(mockHistogramData); + + expect(result).toMatchInlineSnapshot(` + Array [ + Object { + "x": 1669852800000, + "y": 4, + }, + ] + `); + }); + + test('Picks up data from count.doc_count - userAuthentications', () => { + const mockUserAuthentications = [ + { + key_as_string: '2022-12-01T04:00:00.000Z', + key: 1669867200000, + doc_count: 4, + count: { + value: 1, + }, + }, + ]; + const result = formatGeneralHistogramData(mockUserAuthentications); + + expect(result).toMatchInlineSnapshot(` + Array [ + Object { + "x": 1669867200000, + "y": 1, + }, + ] + `); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/common/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts similarity index 54% rename from x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/common/index.ts rename to x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts index fba812666eda8..c52db5b74b8fd 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/common/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts @@ -6,17 +6,17 @@ */ import type { - HostsKpiHistogram, - HostsKpiGeneralHistogramCount, - HostsKpiHistogramData, -} from '../../../../../../../common/search_strategy'; + KpiHistogramData, + KpiGeneralHistogramCount, + KpiHistogram, +} from '../../../../../common/search_strategy'; export const formatGeneralHistogramData = ( - data: Array> -): HostsKpiHistogramData[] | null => + data: Array> +): KpiHistogramData[] | null => data && data.length > 0 - ? data.map(({ key, count }) => ({ + ? data.map(({ key, count }) => ({ x: key, - y: count.value, + y: count.doc_count ?? count.value, })) : null; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts index 4e5fd3454a503..cee0abba2fdb9 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts @@ -16,7 +16,7 @@ import type { import { inspectStringifyObject } from '../../../../../../utils/build_query'; import type { SecuritySolutionFactory } from '../../../types'; import { buildHostsKpiHostsQuery } from './query.hosts_kpi_hosts.dsl'; -import { formatGeneralHistogramData } from '../common'; +import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; export const hostsKpiHosts: SecuritySolutionFactory = { buildDsl: (options: HostsKpiHostsRequestOptions) => buildHostsKpiHostsQuery(options), diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts index 823d523ad92fe..86370222898e3 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts @@ -5,6 +5,5 @@ * 2.0. */ -export * from './common'; export * from './hosts'; export * from './unique_ips'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts index 7e66785d9766d..2147c48b5763a 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts @@ -16,7 +16,7 @@ import type { import { inspectStringifyObject } from '../../../../../../utils/build_query'; import type { SecuritySolutionFactory } from '../../../types'; import { buildHostsKpiUniqueIpsQuery } from './query.hosts_kpi_unique_ips.dsl'; -import { formatGeneralHistogramData } from '../common'; +import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; export const hostsKpiUniqueIps: SecuritySolutionFactory = { buildDsl: (options: HostsKpiUniqueIpsRequestOptions) => buildHostsKpiUniqueIpsQuery(options), diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts index 245b5aa82d0db..e8bba0eaba107 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts @@ -16,7 +16,7 @@ import type { UsersKpiAuthenticationsStrategyResponse, UsersQueries, } from '../../../../../../../common/search_strategy'; -import { formatGeneralHistogramData } from '../../../hosts/kpi'; +import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; export const usersKpiAuthentications: SecuritySolutionFactory = { buildDsl: (options: UsersKpiAuthenticationsRequestOptions) => diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts index 2b9b34d6315c2..1d47f5d034820 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts @@ -21,9 +21,9 @@ import type { } from '../../../../../../../common/search_strategy/security_solution/users/kpi/total_users'; import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import { formatGeneralHistogramData } from '../../../hosts/kpi'; import type { SecuritySolutionFactory } from '../../../types'; import { buildTotalUsersKpiQuery } from './query.build_total_users_kpi.dsl'; +import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; export const totalUsersKpi: SecuritySolutionFactory = { buildDsl: (options: TotalUsersKpiRequestOptions) => buildTotalUsersKpiQuery(options), From 2dde1109e1490f1d955333850109b5623ab86ee9 Mon Sep 17 00:00:00 2001 From: Boris Kirov Date: Mon, 5 Dec 2022 16:05:58 +0100 Subject: [PATCH 11/40] Using the new beta badge icon for the tabs in APM (#146983) Feedback came from @chrisdistasio that the way we show the beta badge in tabs is different across APM. So in this small PR I'm fixing that by utilizing the new `beta` icon and how we should use it, as from EUI and adding it to two places: 1. Service > Infrastructure tab 2. Dependencies> Operations tab OLD image NEW image Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/routing/templates/apm_service_template/index.tsx | 2 +- .../components/routing/templates/dependency_detail_template.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx index 58d97d7916384..a29360bc103e0 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx @@ -270,7 +270,7 @@ function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) { path: { serviceName }, query, }), - append: , + append: , label: i18n.translate('xpack.apm.home.infraTabLabel', { defaultMessage: 'Infrastructure', }), diff --git a/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx index f7cf9734dcdce..833b489004bf3 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx @@ -91,7 +91,7 @@ export function DependencyDetailTemplate({ children }: Props) { isSelected: path === '/dependencies/operations' || path === '/dependencies/operation', - append: , + append: , }, ] : []; From e89ba22953eba604fb61fe1d95ec5cbc7d22a6b8 Mon Sep 17 00:00:00 2001 From: Luke Gmys Date: Mon, 5 Dec 2022 16:12:53 +0100 Subject: [PATCH 12/40] [TIP] Fix broken refresh button on the indicators page (#146526) ## Summary This PR fixes the broken refresh button noticed during the 8.6 demo. Includes an e2e test to verify if it is working or not. ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/threat_intelligence/routes.tsx | 23 +++++++++++++- .../cypress/e2e/indicators.cy.ts | 13 ++++++++ .../cypress/screens/indicators.ts | 2 ++ .../common/mocks/mock_security_context.tsx | 6 +++- .../hooks/use_aggregated_indicators.test.tsx | 5 +++ .../hooks/use_aggregated_indicators.ts | 14 +++++++-- .../indicators/hooks/use_indicators.test.tsx | 6 +++- .../indicators/hooks/use_indicators.ts | 18 ++++++----- .../indicators/pages/indicators.test.tsx | 11 ++++++- .../modules/indicators/pages/indicators.tsx | 11 ++++--- .../public/modules/query_bar/query_bar.tsx | 31 +++++++++++++++++++ .../threat_intelligence/public/plugin.tsx | 4 +-- .../threat_intelligence/public/types.ts | 12 ++++++- 13 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/threat_intelligence/public/modules/query_bar/query_bar.tsx diff --git a/x-pack/plugins/security_solution/public/threat_intelligence/routes.tsx b/x-pack/plugins/security_solution/public/threat_intelligence/routes.tsx index 239ec92d0badd..640d90542c627 100644 --- a/x-pack/plugins/security_solution/public/threat_intelligence/routes.tsx +++ b/x-pack/plugins/security_solution/public/threat_intelligence/routes.tsx @@ -24,6 +24,8 @@ import { useSourcererDataView } from '../common/containers/sourcerer'; import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper'; import { SiemSearchBar } from '../common/components/search_bar'; import { useGlobalTime } from '../common/containers/use_global_time'; +import { deleteOneQuery, setQuery } from '../common/store/inputs/actions'; +import { InputsModelId } from '../common/store/inputs/constants'; const ThreatIntelligence = memo(() => { const { threatIntelligence } = useKibana().services; @@ -34,17 +36,36 @@ const ThreatIntelligence = memo(() => { const securitySolutionStore = getStore() as Store; const securitySolutionContext: SecuritySolutionPluginContext = { + securitySolutionStore, + getFiltersGlobalComponent: () => FiltersGlobal, getPageWrapper: () => SecuritySolutionPageWrapper, licenseService, sourcererDataView: sourcererDataView as unknown as SourcererDataView, - getSecuritySolutionStore: securitySolutionStore, getUseInvestigateInTimeline: useInvestigateInTimeline, useQuery: () => useSelector(inputsSelectors.globalQuerySelector()), useFilters: () => useSelector(inputsSelectors.globalFiltersQuerySelector()), useGlobalTime, + registerQuery: (query) => + securitySolutionStore.dispatch( + setQuery({ + inputId: InputsModelId.global, + id: query.id, + refetch: query.refetch, + inspect: null, + loading: query.loading, + }) + ), + deregisterQuery: (query) => + securitySolutionStore.dispatch( + deleteOneQuery({ + inputId: InputsModelId.global, + id: query.id, + }) + ), + SiemSearchBar, }; diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts index 87a5b2538636c..da5af8f6632d9 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts @@ -40,6 +40,7 @@ import { TABLE_CONTROLS, TIME_RANGE_PICKER, TOGGLE_FLYOUT_BUTTON, + REFRESH_BUTTON, } from '../screens/indicators'; import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; @@ -232,6 +233,18 @@ describe('Indicators', () => { cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 1-25 of'); }); + it('should reload the data when refresh button is pressed', () => { + cy.intercept(/bsearch/).as('search'); + + cy.get(REFRESH_BUTTON).should('exist').click(); + + cy.wait('@search'); + + cy.get(REFRESH_BUTTON).should('exist').click(); + + cy.wait('@search'); + }); + describe('No items match search criteria', () => { before(() => { // Contradictory filter set diff --git a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts index 94eb2e46c350e..3a2650601f7a6 100644 --- a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts +++ b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts @@ -198,3 +198,5 @@ export const INSPECTOR_BUTTON = '[data-test-subj="tiIndicatorsGridInspect"]'; export const INSPECTOR_PANEL = '[data-test-subj="inspectorPanel"]'; export const ADD_INTEGRATIONS_BUTTON = '[data-test-subj="add-data"]'; + +export const REFRESH_BUTTON = '[data-test-subj="querySubmitButton"]'; diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx index 8a0bb088e064d..77398772a3bb2 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx @@ -28,7 +28,7 @@ export const getSecuritySolutionContextMock = (): SecuritySolutionPluginContext indexPattern: { fields: [], title: '' }, loading: false, }, - getSecuritySolutionStore: { + securitySolutionStore: { // @ts-ignore dispatch: () => jest.fn(), }, @@ -44,4 +44,8 @@ export const getSecuritySolutionContextMock = (): SecuritySolutionPluginContext useGlobalTime: () => ({ from: '', to: '' }), useQuery: () => ({ language: 'kuery', query: '' }), + + registerQuery: () => {}, + + deregisterQuery: () => {}, }); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx index 04ca3311955f0..69c00247079c7 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx @@ -95,6 +95,11 @@ describe('useAggregatedIndicators()', () => { "isFetching": false, "isLoading": false, "onFieldChange": [Function], + "query": Object { + "id": "indicatorsBarchart", + "loading": false, + "refetch": [Function], + }, "selectedField": "threat.feed.name", "series": Array [], } diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts index bdfd9fafa77e0..805342f87a2fd 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts @@ -56,10 +56,14 @@ export interface UseAggregatedIndicatorsValue { /** Is data update in progress? */ isFetching?: boolean; + + query: { refetch: VoidFunction; id: string; loading: boolean }; } const DEFAULT_FIELD = RawIndicatorFieldId.Feed; +const QUERY_ID = 'indicatorsBarchart'; + export const useAggregatedIndicators = ({ timeRange, filters, @@ -87,9 +91,9 @@ export const useAggregatedIndicators = ({ [inspectorAdapters, queryService, searchService] ); - const { data, isLoading, isFetching } = useQuery( + const { data, isLoading, isFetching, refetch } = useQuery( [ - 'indicatorsBarchart', + QUERY_ID, { filters, field, @@ -113,6 +117,11 @@ export const useAggregatedIndicators = ({ [queryService.timefilter.timefilter, timeRange] ); + const query = useMemo( + () => ({ refetch, id: QUERY_ID, loading: isLoading }), + [isLoading, refetch] + ); + return { dateRange, series: data || [], @@ -120,5 +129,6 @@ export const useAggregatedIndicators = ({ selectedField: field, isLoading, isFetching, + query, }; }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx index 9292321658e86..0eac3f2cca674 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx @@ -106,7 +106,6 @@ describe('useIndicators()', () => { expect(hookResult.result.current).toMatchInlineSnapshot(` Object { "dataUpdatedAt": 0, - "handleRefresh": [Function], "indicatorCount": 0, "indicators": Array [], "isFetching": false, @@ -122,6 +121,11 @@ describe('useIndicators()', () => { 50, ], }, + "query": Object { + "id": "indicatorsTable", + "loading": false, + "refetch": [Function], + }, } `); }); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts index 3011d9b5101f6..b1f0b17a8fd2b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts @@ -26,8 +26,6 @@ export interface UseIndicatorsParams { } export interface UseIndicatorsValue { - handleRefresh: () => void; - /** * Array of {@link Indicator} ready to render inside the IndicatorTable component */ @@ -48,8 +46,12 @@ export interface UseIndicatorsValue { isFetching: boolean; dataUpdatedAt: number; + + query: { refetch: VoidFunction; id: string; loading: boolean }; } +const QUERY_ID = 'indicatorsTable'; + export const useIndicators = ({ filters, filterQuery, @@ -98,7 +100,7 @@ export const useIndicators = ({ const { isLoading, isFetching, data, refetch, dataUpdatedAt } = useQuery( [ - 'indicatorsTable', + QUERY_ID, { timeRange, filterQuery, @@ -119,10 +121,10 @@ export const useIndicators = ({ } ); - const handleRefresh = useCallback(() => { - onChangePage(0); - refetch(); - }, [onChangePage, refetch]); + const query = useMemo( + () => ({ refetch, id: QUERY_ID, loading: isLoading }), + [isLoading, refetch] + ); return { indicators: data?.indicators || [], @@ -132,7 +134,7 @@ export const useIndicators = ({ onChangeItemsPerPage, isLoading, isFetching, - handleRefresh, dataUpdatedAt, + query, }; }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx index d51410857c26e..d8f48689c1df0 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx @@ -30,6 +30,11 @@ describe('', () => { series: [], selectedField: '', onFieldChange: () => {}, + query: { + id: 'chart', + loading: false, + refetch: stub, + }, }); (useIndicators as jest.MockedFunction).mockReturnValue({ @@ -40,8 +45,12 @@ describe('', () => { pagination: { pageIndex: 0, pageSize: 10, pageSizeOptions: [10] }, onChangeItemsPerPage: stub, onChangePage: stub, - handleRefresh: stub, dataUpdatedAt: Date.now(), + query: { + id: 'list', + loading: false, + refetch: stub, + }, }); (useFilters as jest.MockedFunction).mockReturnValue({ diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx index f161b7ac1d85c..aaac18f3fb215 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx @@ -16,8 +16,8 @@ import { FieldTypesProvider } from '../../../containers/field_types_provider'; import { InspectorProvider } from '../../../containers/inspector'; import { useColumnSettings } from '../components/table/hooks'; import { IndicatorsFilters } from '../containers/filters'; -import { useSecurityContext } from '../../../hooks'; import { UpdateStatus } from '../../../components/update_status'; +import { QueryBar } from '../../query_bar/query_bar'; const IndicatorsPageProviders: FC = ({ children }) => ( @@ -43,6 +43,7 @@ const IndicatorsPageContent: VFC = () => { isLoading: isLoadingIndicators, isFetching: isFetchingIndicators, dataUpdatedAt, + query: indicatorListQuery, } = useIndicators({ filters, filterQuery, @@ -57,14 +58,13 @@ const IndicatorsPageContent: VFC = () => { onFieldChange, isLoading: isLoadingAggregatedIndicators, isFetching: isFetchingAggregatedIndicators, + query: indicatorChartQuery, } = useAggregatedIndicators({ timeRange, filters, filterQuery, }); - const { SiemSearchBar } = useSecurityContext(); - return ( { subHeader={} > - + ; +} + +export const QueryBar: VFC = ({ indexPattern, queries }) => { + const { SiemSearchBar, registerQuery, deregisterQuery } = useSecurityContext(); + + useEffect(() => { + queries.forEach(registerQuery); + + return () => queries.forEach(deregisterQuery); + }, [queries, deregisterQuery, registerQuery]); + + return ; +}; diff --git a/x-pack/plugins/threat_intelligence/public/plugin.tsx b/x-pack/plugins/threat_intelligence/public/plugin.tsx index 6fc058131af9b..3fcbdde60f560 100755 --- a/x-pack/plugins/threat_intelligence/public/plugin.tsx +++ b/x-pack/plugins/threat_intelligence/public/plugin.tsx @@ -32,7 +32,7 @@ const LazyIndicatorsPageWrapper = React.lazy(() => import('./containers/indicato /** * This is used here: - * x-pack/plugins/security_solution/public/threat_intelligence/pages/threat_intelligence.tsx + * x-pack/plugins/security_solution/public/threat_intelligence/routes.tsx */ export const createApp = (services: Services) => @@ -40,7 +40,7 @@ export const createApp = ({ securitySolutionContext }: AppProps) => ( - + diff --git a/x-pack/plugins/threat_intelligence/public/types.ts b/x-pack/plugins/threat_intelligence/public/types.ts index 673a44494ac18..9b11c705a20d0 100644 --- a/x-pack/plugins/threat_intelligence/public/types.ts +++ b/x-pack/plugins/threat_intelligence/public/types.ts @@ -99,7 +99,7 @@ export interface SecuritySolutionPluginContext { /** * Security Solution store */ - getSecuritySolutionStore: Store; + securitySolutionStore: Store; /** * Pass UseInvestigateInTimeline functionality to TI plugin */ @@ -114,4 +114,14 @@ export interface SecuritySolutionPluginContext { useGlobalTime: () => TimeRange; SiemSearchBar: VFC; + + /** + * Register query in security solution store for tracking and centralized refresh support + */ + registerQuery: (query: { id: string; loading: boolean; refetch: VoidFunction }) => void; + + /** + * Deregister stale query + */ + deregisterQuery: (query: { id: string }) => void; } From c7bd2ffea52bd9578c002d239d4bf956715f1f99 Mon Sep 17 00:00:00 2001 From: Julian Gernun <17549662+jcger@users.noreply.github.com> Date: Mon, 5 Dec 2022 16:26:20 +0100 Subject: [PATCH 13/40] [RAM] fix create rule titles font-size (#147001) ## Summary Closes https://github.com/elastic/kibana/issues/145999 Screenshot with applied changes: ![Screenshot 2022-12-05 at 15 23 21](https://user-images.githubusercontent.com/17549662/205660619-137f01c9-673a-468a-8a00-e8253c60d9cd.png) --- .../public/application/sections/rule_form/rule_form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx index d37e41ff26555..16dc1642c584c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx @@ -386,7 +386,7 @@ export const RuleForm = ({ - + {items .sort((a, b) => ruleTypeCompare(a, b)) .map((item, index) => { From b0bd289f85143ca8e456b818fa5b5203446c61bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Mon, 5 Dec 2022 10:37:32 -0500 Subject: [PATCH 14/40] Speed up enqueueing of rule actions (#146239) In this PR, I'm making the bulk enqueueing of rule actions faster by avoiding to wait for an index refresh when creating the `action_task_params` saved objects. The removal of waiting for a refresh speeds up the rule executions by ~500ms when there are actions to enqueue for alerts. ## To verify 1. Create an alerting rule that fires actions 2. Notice the actions are running successfully You can also compare run times with main when doing your verification steps. A simple index threshold firing one action would go from 100ms-1000ms to a more consistent 100ms runtime.. ## Note to reviewer(s) It's easier to review the test changes if you append `?w=1` to the URL when looking at the file diff. It will remove whitespace differences and show fewer lines changed. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/create_execute_function.test.ts | 223 ++++++++++-------- .../actions/server/create_execute_function.ts | 2 +- 2 files changed, 120 insertions(+), 105 deletions(-) diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index a38a9e4a0e780..6e1c9aded6a3d 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -605,24 +605,27 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([{ id: '123', type: 'action' }]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: '123', + name: 'actionRef', + type: 'action', + }, + ], + }, + ], + { refresh: false } + ); expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { notifyUsage: true, }); @@ -691,25 +694,28 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([{ id: '123', type: 'action' }]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - consumer: 'test-consumer', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + consumer: 'test-consumer', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: '123', + name: 'actionRef', + type: 'action', + }, + ], + }, + ], + { refresh: false } + ); expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { notifyUsage: true, }); @@ -763,37 +769,40 @@ describe('bulkExecute()', () => { ], }, ]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - relatedSavedObjects: [ + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + executionId: '123abc', + relatedSavedObjects: [ + { + id: 'related_some-type_0', + namespace: 'some-namespace', + type: 'some-type', + typeId: 'some-typeId', + }, + ], + }, + references: [ { - id: 'related_some-type_0', - namespace: 'some-namespace', + id: '123', + name: 'actionRef', + type: 'action', + }, + { + id: 'some-id', + name: 'related_some-type_0', type: 'some-type', - typeId: 'some-typeId', }, ], }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - }, - ]); + ], + { refresh: false } + ); }); test('schedules the action with all given parameters with a preconfigured action', async () => { @@ -868,24 +877,27 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: source.id, - name: 'source', - type: source.type, + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: source.id, + name: 'source', + type: source.type, + }, + ], + }, + ], + { refresh: false } + ); }); test('schedules the action with all given parameters with a preconfigured action and relatedSavedObjects', async () => { @@ -968,37 +980,40 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - relatedSavedObjects: [ + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + executionId: '123abc', + relatedSavedObjects: [ + { + id: 'related_some-type_0', + namespace: 'some-namespace', + type: 'some-type', + typeId: 'some-typeId', + }, + ], + }, + references: [ { - id: 'related_some-type_0', - namespace: 'some-namespace', + id: source.id, + name: 'source', + type: source.type, + }, + { + id: 'some-id', + name: 'related_some-type_0', type: 'some-type', - typeId: 'some-typeId', }, ], }, - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - }, - ]); + ], + { refresh: false } + ); }); test('throws when passing isESOCanEncrypt with false as a value', async () => { diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 19447bf8e79e5..c050cf34c9fca 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -207,7 +207,7 @@ export function createBulkExecutionEnqueuerFunction({ }; }); const actionTaskParamsRecords: SavedObjectsBulkResponse = - await unsecuredSavedObjectsClient.bulkCreate(actions); + await unsecuredSavedObjectsClient.bulkCreate(actions, { refresh: false }); const taskInstances = actionTaskParamsRecords.saved_objects.map((so) => { const actionId = so.attributes.actionId; return { From 6ee9cbf08e830d375fa17d1601b25e64c745ab29 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Mon, 5 Dec 2022 15:42:36 +0000 Subject: [PATCH 15/40] [Fleet][ON week] Remove extra manifest cache (#146987) ## Summary When looking into archive parsing performance i noticed we have another "secret" manifest buffer cache. Removing this doesn't affect performance and reduces kibana's memory usage after running `node scripts/get_all_packages` by approx 40mb. bonus: make get_all_packages script error more informative Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../get_all_packages/get_all_packages.ts | 39 ++++++++------- .../server/services/epm/archive/parse.ts | 48 +++++++++++-------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/fleet/scripts/get_all_packages/get_all_packages.ts b/x-pack/plugins/fleet/scripts/get_all_packages/get_all_packages.ts index 74ea305b45bb9..481ed9d615400 100644 --- a/x-pack/plugins/fleet/scripts/get_all_packages/get_all_packages.ts +++ b/x-pack/plugins/fleet/scripts/get_all_packages/get_all_packages.ts @@ -35,28 +35,31 @@ interface Result { } async function getPackage(name: string, version: string, full: boolean = false) { const start = Date.now(); - const res = await fetch( - `${KIBANA_URL}${base}/api/fleet/epm/packages/${name}/${version}?prerelease=true${ - full ? '&full=true' : '' - }`, - { - headers: { - accept: '*/*', - 'content-type': 'application/json', - 'kbn-xsrf': 'xyz', - Authorization: - 'Basic ' + Buffer.from(`${KIBANA_USERNAME}:${KIBANA_PASSWORD}`).toString('base64'), - }, - method: 'GET', - } - ); - const end = Date.now(); - let body; + let end; + let res; try { + res = await fetch( + `${KIBANA_URL}${base}/api/fleet/epm/packages/${name}/${version}?prerelease=true${ + full ? '&full=true' : '' + }`, + { + headers: { + accept: '*/*', + 'content-type': 'application/json', + 'kbn-xsrf': 'xyz', + Authorization: + 'Basic ' + Buffer.from(`${KIBANA_USERNAME}:${KIBANA_PASSWORD}`).toString('base64'), + }, + method: 'GET', + } + ); + end = Date.now(); + body = await res.json(); } catch (e) { - logger.error(`Error parsing response: ${e}`); + logger.error(`Error reaching Kibana: ${e}`); + logger.info('If your kibana uses a base path, please set it with the --base / flag'); throw e; } diff --git a/x-pack/plugins/fleet/server/services/epm/archive/parse.ts b/x-pack/plugins/fleet/server/services/epm/archive/parse.ts index 1007b1fe35344..9ef677b796ce8 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/parse.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/parse.ts @@ -38,7 +38,6 @@ import { pkgToPkgKey } from '../registry'; import { unpackBufferEntries } from '.'; const readFileAsync = promisify(readFile); -const MANIFESTS: Record = {}; const MANIFEST_NAME = 'manifest.yml'; const DEFAULT_RELEASE_VALUE = 'ga'; @@ -80,6 +79,8 @@ export const expandDottedEntries = (obj: object) => { }, {} as Record); }; +type ManifestMap = Record; + // not sure these are 100% correct but they do the job here // keeping them local until others need them type OptionalPropertyOf = Exclude< @@ -140,15 +141,16 @@ export async function generatePackageInfoFromArchiveBuffer( archiveBuffer: Buffer, contentType: string ): Promise<{ paths: string[]; packageInfo: ArchivePackage }> { + const manifests: ManifestMap = {}; const entries = await unpackBufferEntries(archiveBuffer, contentType); const paths: string[] = []; entries.forEach(({ path: bufferPath, buffer }) => { paths.push(bufferPath); - if (bufferPath.endsWith(MANIFEST_NAME) && buffer) MANIFESTS[bufferPath] = buffer; + if (bufferPath.endsWith(MANIFEST_NAME) && buffer) manifests[bufferPath] = buffer; }); return { - packageInfo: parseAndVerifyArchive(paths), + packageInfo: parseAndVerifyArchive(paths, manifests), paths, }; } @@ -161,15 +163,20 @@ export async function _generatePackageInfoFromPaths( paths: string[], topLevelDir: string ): Promise { + const manifests: ManifestMap = {}; await Promise.all( paths.map(async (filePath) => { - if (filePath.endsWith(MANIFEST_NAME)) MANIFESTS[filePath] = await readFileAsync(filePath); + if (filePath.endsWith(MANIFEST_NAME)) manifests[filePath] = await readFileAsync(filePath); }) ); - return parseAndVerifyArchive(paths, topLevelDir); + return parseAndVerifyArchive(paths, manifests, topLevelDir); } -function parseAndVerifyArchive(paths: string[], topLevelDirOverride?: string): ArchivePackage { +function parseAndVerifyArchive( + paths: string[], + manifests: ManifestMap, + topLevelDirOverride?: string +): ArchivePackage { // The top-level directory must match pkgName-pkgVersion, and no other top-level files or directories may be present const toplevelDir = topLevelDirOverride || paths[0].split('/')[0]; paths.forEach((filePath) => { @@ -180,7 +187,7 @@ function parseAndVerifyArchive(paths: string[], topLevelDirOverride?: string): A // The package must contain a manifest file ... const manifestFile = path.posix.join(toplevelDir, MANIFEST_NAME); - const manifestBuffer = MANIFESTS[manifestFile]; + const manifestBuffer = manifests[manifestFile]; if (!paths.includes(manifestFile) || !manifestBuffer) { throw new PackageInvalidArchiveError(`Package must contain a top-level ${MANIFEST_NAME} file.`); } @@ -217,12 +224,13 @@ function parseAndVerifyArchive(paths: string[], topLevelDirOverride?: string): A ); } - const parsedDataStreams = parseAndVerifyDataStreams( + const parsedDataStreams = parseAndVerifyDataStreams({ paths, - parsed.name, - parsed.version, - topLevelDirOverride - ); + pkgName: parsed.name, + pkgVersion: parsed.version, + pkgBasePathOverride: topLevelDirOverride, + manifests, + }); if (parsedDataStreams.length) { parsed.data_streams = parsedDataStreams; @@ -253,12 +261,14 @@ function parseAndVerifyReadme(paths: string[], pkgName: string, pkgVersion: stri return paths.includes(readmePath) ? `/package/${pkgName}/${pkgVersion}${readmeRelPath}` : null; } -export function parseAndVerifyDataStreams( - paths: string[], - pkgName: string, - pkgVersion: string, - pkgBasePathOverride?: string -): RegistryDataStream[] { +export function parseAndVerifyDataStreams(opts: { + paths: string[]; + pkgName: string; + pkgVersion: string; + manifests: ManifestMap; + pkgBasePathOverride?: string; +}): RegistryDataStream[] { + const { paths, pkgName, pkgVersion, manifests, pkgBasePathOverride } = opts; // A data stream is made up of a subdirectory of name-version/data_stream/, containing a manifest.yml const dataStreamPaths = new Set(); const dataStreams: RegistryDataStream[] = []; @@ -277,7 +287,7 @@ export function parseAndVerifyDataStreams( dataStreamPaths.forEach((dataStreamPath) => { const fullDataStreamPath = path.posix.join(dataStreamsBasePath, dataStreamPath); const manifestFile = path.posix.join(fullDataStreamPath, MANIFEST_NAME); - const manifestBuffer = MANIFESTS[manifestFile]; + const manifestBuffer = manifests[manifestFile]; if (!paths.includes(manifestFile) || !manifestBuffer) { throw new PackageInvalidArchiveError( `No manifest.yml file found for data stream '${dataStreamPath}'` From 390e5e35b2d8f31e880b77e60f8261babcdfb034 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 5 Dec 2022 17:28:08 +0100 Subject: [PATCH 16/40] [ResponseOps][Cases] Fix jest warning logs (#146965) Fixes #141414 ## Summary Fixed the following warnings: > Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state. [...] This caused warnings in the following tests: - x-pack/plugins/cases/public/components/all_cases/index.test.tsx - x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx > An update to TestComponent inside a test was not wrapped in act(...). This caused warnings in the following tests: - x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx - x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx - x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx Other findings: > `componentWillUpdate` has been renamed and is not recommended for use. I could not find instances of this anywhere in Cases. I suspect it comes from Eui. > Can't perform a React state update on an unmounted component. [This warning was actually removed on React 18.](https://github.com/reactwg/react-18/discussions/82) --- ..._cases_add_to_existing_case_modal.test.tsx | 5 +- .../use_cases_add_to_existing_case_modal.tsx | 1 + .../all_cases/use_all_cases_query_params.tsx | 12 ++-- .../case_view/case_view_page.test.tsx | 72 ++++++++++++------- .../containers/use_get_feature_ids.test.tsx | 15 ++-- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx index d14787fee4a53..cc164b2396f60 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx @@ -83,6 +83,7 @@ describe('use cases add to existing case modal hook', () => { const defaultParams = () => { return { onRowClick: jest.fn() }; }; + beforeEach(() => { appMockRender = createAppMockRenderer(); dispatch.mockReset(); @@ -166,7 +167,7 @@ describe('use cases add to existing case modal hook', () => { expect(mockedToastSuccess).toHaveBeenCalled(); }); - it('should not call createAttachments nor show toast success when a case is not selected', async () => { + it('should not call createAttachments nor show toast success when a case is not selected', async () => { const mockBulkCreateAttachments = jest.fn(); useCreateAttachmentsMock.mockReturnValueOnce({ createAttachments: mockBulkCreateAttachments, @@ -178,11 +179,11 @@ describe('use cases add to existing case modal hook', () => { }); AllCasesSelectorModalMock.mockImplementation(({ onRowClick }) => { - onRowClick(); return null; }); const result = appMockRender.render(); + userEvent.click(result.getByTestId('open-modal')); // give a small delay for the reducer to run diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx index 2936ebf56d1e3..057973f82e0d2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx @@ -123,6 +123,7 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps = }, [closeModal, dispatch, handleOnRowClick, props] ); + return { open: openModal, close: closeModal, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx index 9a094d3f45d55..d2c03d5e6ddab 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { useCallback, useRef, useState } from 'react'; +import { useCallback, useRef, useState, useEffect } from 'react'; import { useLocation, useHistory } from 'react-router-dom'; import { isEqual } from 'lodash'; @@ -121,10 +121,12 @@ export function useAllCasesQueryParams(isModalView: boolean = false) { ] ); - if (isFirstRenderRef.current) { - persistAndUpdateQueryParams(isModalView ? DEFAULT_QUERY_PARAMS : {}); - isFirstRenderRef.current = false; - } + useEffect(() => { + if (isFirstRenderRef.current) { + persistAndUpdateQueryParams(isModalView ? DEFAULT_QUERY_PARAMS : {}); + isFirstRenderRef.current = false; + } + }, [isModalView, persistAndUpdateQueryParams]); return { queryParams, diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index 7a299257b8017..aff92e15c3f29 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -171,9 +171,9 @@ describe('CaseViewPage', () => { userEvent.click(dropdown.querySelector('button')!); await waitForEuiPopoverOpen(); userEvent.click(result.getByTestId('case-view-status-dropdown-closed')); + const updateObject = updateCaseProperty.mock.calls[0][0]; await waitFor(() => { - const updateObject = updateCaseProperty.mock.calls[0][0]; expect(updateCaseProperty).toHaveBeenCalledTimes(1); expect(updateObject.updateKey).toEqual('status'); expect(updateObject.updateValue).toEqual('closed'); @@ -187,8 +187,11 @@ describe('CaseViewPage', () => { updateKey: 'title', })); const result = appMockRenderer.render(); - expect(result.getByTestId('editable-title-loading')).toBeInTheDocument(); - expect(result.queryByTestId('editable-title-edit-icon')).not.toBeInTheDocument(); + + await waitFor(() => { + expect(result.getByTestId('editable-title-loading')).toBeInTheDocument(); + expect(result.queryByTestId('editable-title-edit-icon')).not.toBeInTheDocument(); + }); }); it('should display description isLoading', async () => { @@ -197,13 +200,17 @@ describe('CaseViewPage', () => { isLoading: true, updateKey: 'description', })); + const result = appMockRenderer.render(); - expect( - within(result.getByTestId('description-action')).getByTestId('user-action-title-loading') - ).toBeInTheDocument(); - expect( - within(result.getByTestId('description-action')).queryByTestId('property-actions') - ).not.toBeInTheDocument(); + + await waitFor(() => { + expect( + within(result.getByTestId('description-action')).getByTestId('user-action-title-loading') + ).toBeInTheDocument(); + expect( + within(result.getByTestId('description-action')).queryByTestId('property-actions') + ).not.toBeInTheDocument(); + }); }); it('should display tags isLoading', async () => { @@ -212,11 +219,18 @@ describe('CaseViewPage', () => { isLoading: true, updateKey: 'tags', })); + const result = appMockRenderer.render(); - expect( - within(result.getByTestId('case-view-tag-list')).getByTestId('tag-list-loading') - ).toBeInTheDocument(); - expect(result.queryByTestId('tag-list-edit')).not.toBeInTheDocument(); + + await waitFor(() => { + expect( + within(result.getByTestId('case-view-tag-list')).getByTestId('tag-list-loading') + ).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(result.queryByTestId('tag-list-edit')).not.toBeInTheDocument(); + }); }); it('should update title', async () => { @@ -228,8 +242,10 @@ describe('CaseViewPage', () => { userEvent.click(result.getByTestId('editable-title-submit-btn')); const updateObject = updateCaseProperty.mock.calls[0][0]; - expect(updateObject.updateKey).toEqual('title'); - expect(updateObject.updateValue).toEqual(newTitle); + await waitFor(() => { + expect(updateObject.updateKey).toEqual('title'); + expect(updateObject.updateValue).toEqual(newTitle); + }); }); it('should push updates on button click', async () => { @@ -244,6 +260,7 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render(); expect(result.getByTestId('has-data-to-push-button')).toBeInTheDocument(); + userEvent.click(result.getByTestId('push-to-external-service')); await waitFor(() => { @@ -260,7 +277,9 @@ describe('CaseViewPage', () => { }} /> ); - expect(result.getByTestId('push-to-external-service')).toBeDisabled(); + await waitFor(() => { + expect(result.getByTestId('push-to-external-service')).toBeDisabled(); + }); }); it('should update connector', async () => { @@ -328,8 +347,10 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render( ); - expect(result.getByTestId('case-view-loading-content')).toBeInTheDocument(); - expect(result.queryByTestId('user-actions')).not.toBeInTheDocument(); + await waitFor(() => { + expect(result.getByTestId('case-view-loading-content')).toBeInTheDocument(); + expect(result.queryByTestId('user-actions')).not.toBeInTheDocument(); + }); }); it('should call show alert details with expected arguments', async () => { @@ -348,19 +369,21 @@ describe('CaseViewPage', () => { it('should show the rule name', async () => { const result = appMockRenderer.render(); - expect( - result - .getByTestId('user-action-alert-comment-create-action-alert-action-id') - .querySelector('.euiCommentEvent__headerEvent') - ).toHaveTextContent('added an alert from Awesome rule'); + await waitFor(() => { + expect( + result + .getByTestId('user-action-alert-comment-create-action-alert-action-id') + .querySelector('.euiCommentEvent__headerEvent') + ).toHaveTextContent('added an alert from Awesome rule'); + }); }); it('should update settings', async () => { const result = appMockRenderer.render(); userEvent.click(result.getByTestId('sync-alerts-switch')); + const updateObject = updateCaseProperty.mock.calls[0][0]; await waitFor(() => { - const updateObject = updateCaseProperty.mock.calls[0][0]; expect(updateObject.updateKey).toEqual('settings'); expect(updateObject.updateValue).toEqual({ syncAlerts: false }); }); @@ -379,6 +402,7 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render( ); + await waitFor(() => { expect(result.getByTestId('has-data-to-push-button')).toHaveTextContent('My Connector 2'); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx index b173ea4ad19e0..3d4382bc709ab 100644 --- a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { TestProviders } from '../common/mock'; import { useGetFeatureIds } from './use_get_feature_ids'; import * as api from './api'; -import { waitFor } from '@testing-library/dom'; jest.mock('./api'); jest.mock('../common/lib/kibana'); @@ -27,29 +26,31 @@ describe('useGetFeaturesIds', () => { wrapper: ({ children }) => {children}, }); - act(() => { + await act(async () => { expect(result.current.alertFeatureIds).toEqual([]); expect(result.current.isLoading).toEqual(true); expect(result.current.isError).toEqual(false); }); }); - // + it('fetches data and returns it correctly', async () => { const spy = jest.spyOn(api, 'getFeatureIds'); const { result } = renderHook(() => useGetFeatureIds(['context1']), { wrapper: ({ children }) => {children}, }); - await waitFor(() => { + await act(async () => { expect(spy).toHaveBeenCalledWith( { registrationContext: ['context1'] }, expect.any(AbortSignal) ); }); - expect(result.current.alertFeatureIds).toEqual(['siem', 'observability']); - expect(result.current.isLoading).toEqual(false); - expect(result.current.isError).toEqual(false); + await act(async () => { + expect(result.current.alertFeatureIds).toEqual(['siem', 'observability']); + expect(result.current.isLoading).toEqual(false); + expect(result.current.isError).toEqual(false); + }); }); it('sets isError to true when an error occurs', async () => { From b5ba42bf1af74bea87619d7ebaa1d48cab88b7d3 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 5 Dec 2022 11:46:15 -0500 Subject: [PATCH 17/40] [Security Solution] Change Actions Log Management text to Response Actions History (#146918) ## Summary Update the "Actions Log Management" text to be "Response Actions History" image ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/security_solution/server/features.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/server/features.ts b/x-pack/plugins/security_solution/server/features.ts index 08cd06890f298..e940dfe6d0c6a 100644 --- a/x-pack/plugins/security_solution/server/features.ts +++ b/x-pack/plugins/security_solution/server/features.ts @@ -106,15 +106,15 @@ const responseActionSubFeatures: SubFeatureConfig[] = [ { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.actionsLogManagement.privilegesTooltip', + 'xpack.securitySolution.featureRegistry.subFeatures.responseActionsHistory.privilegesTooltip', { - defaultMessage: 'All Spaces is required for Actions Log Management access.', + defaultMessage: 'All Spaces is required for Response Actions History access.', } ), name: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.actionsLogManagement', + 'xpack.securitySolution.featureRegistry.subFeatures.responseActionsHistory', { - defaultMessage: 'Actions Log Management', + defaultMessage: 'Response Actions History', } ), privilegeGroups: [ From 035ebc4106f2d9fae1983384c44e0032669307a1 Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Mon, 5 Dec 2022 17:52:16 +0100 Subject: [PATCH 18/40] [Fleet] Spacetime: Add fleet server health check to debug page (#146594) ## Summary Closes https://github.com/elastic/ingest-dev/issues/1422 Closes https://github.com/elastic/kibana/issues/143644 Fixes https://github.com/elastic/kibana/issues/141635 ### Description Spacetime project: - Fixing UI layout - Adding a new endpoint to check the connection to fleet-server. The endpoint executes `curl -s -k /api/status` and can be called from dev tools as: ``` POST kbn:/api/fleet/health_check { "host": $hostname } ``` Where `$hostname` is the host configured in fleet server hosts settings section. - Adding a Fleet Server health check to the debug page `app/fleet/_debug`. The host can be selected via a dropdown. - Moving debug page outside of setup to allow debugging when fleet couldn't initialise. I added a warning on top of the page in this specific case - https://github.com/elastic/kibana/issues/143644 - Added some more saved objects and indices that weren't added the first time round to allow further debugging. ### Repro steps: To try that the page loads even when setup didn't work, I changed some values in the code. Comment out [this code](https://github.com/elastic/kibana/blob/main/x-pack/plugins/fleet/public/applications/fleet/app.tsx#L163-L165) and replace it with `setInitializationError({ name: 'error', message: 'unable to initialize' });`, then set `false` in [here](https://github.com/elastic/kibana/blob/b155134d662b8011857f7763a063ce87b3b6a91d/x-pack/plugins/fleet/public/applications/fleet/app.tsx#L179) and the fleet UI should show a setup error, however now the debug page should be visible. ### Screenshots Screenshot 2022-11-30 at 15 25 51 Screenshot 2022-11-30 at 15 26 36 Screenshot 2022-11-30 at 15 27 09 Screenshot 2022-12-01 at 17 36 57 ### Checklist - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/fleet/common/services/routes.ts | 1 + .../common/types/rest_spec/health_check.ts | 18 ++ .../fleet/common/types/rest_spec/index.ts | 1 + .../fleet/public/applications/fleet/app.tsx | 9 +- .../debug/components/fleet_index_debugger.tsx | 2 + .../debug/components/health_check_panel.tsx | 167 +++++++++++++++ .../fleet/sections/debug/components/index.tsx | 1 + .../components/preconfiguration_debugger.tsx | 2 +- .../components/saved_object_debugger.tsx | 31 ++- .../fleet/sections/debug/index.tsx | 197 ++++++++++-------- .../public/hooks/use_request/health_check.ts | 19 ++ .../fleet/public/hooks/use_request/index.ts | 1 + x-pack/plugins/fleet/public/types/index.ts | 2 + .../fleet/server/routes/health_check/index.ts | 60 ++++-- .../server/types/rest_spec/health_check.ts | 14 ++ .../fleet/server/types/rest_spec/index.ts | 1 + 16 files changed, 422 insertions(+), 104 deletions(-) create mode 100644 x-pack/plugins/fleet/common/types/rest_spec/health_check.ts create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/health_check_panel.tsx create mode 100644 x-pack/plugins/fleet/public/hooks/use_request/health_check.ts create mode 100644 x-pack/plugins/fleet/server/types/rest_spec/health_check.ts diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index 354834fc896c5..59c158fe4dee1 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -259,6 +259,7 @@ export const settingsRoutesService = { export const appRoutesService = { getCheckPermissionsPath: (fleetServerSetup?: boolean) => APP_API_ROUTES.CHECK_PERMISSIONS_PATTERN, getRegenerateServiceTokenPath: () => APP_API_ROUTES.GENERATE_SERVICE_TOKEN_PATTERN, + postHealthCheckPath: () => APP_API_ROUTES.HEALTH_CHECK_PATTERN, }; export const enrollmentAPIKeyRouteService = { diff --git a/x-pack/plugins/fleet/common/types/rest_spec/health_check.ts b/x-pack/plugins/fleet/common/types/rest_spec/health_check.ts new file mode 100644 index 0000000000000..c718081344236 --- /dev/null +++ b/x-pack/plugins/fleet/common/types/rest_spec/health_check.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export interface PostHealthCheckRequest { + body: { + host: string; + }; +} + +export interface PostHealthCheckResponse { + name: string; + host: string; + status: string; +} diff --git a/x-pack/plugins/fleet/common/types/rest_spec/index.ts b/x-pack/plugins/fleet/common/types/rest_spec/index.ts index 989e65209bf9d..e52937c16ac3c 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/index.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/index.ts @@ -18,3 +18,4 @@ export * from './fleet_setup'; export * from './output'; export * from './package_policy'; export * from './settings'; +export * from './health_check'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index 8af6db71106b3..9afe8c10e18c3 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -146,6 +146,7 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { const [initializationError, setInitializationError] = useState(null); const isAddIntegrationsPath = !!useRouteMatch(FLEET_ROUTING_PATHS.add_integration_to_policy); + const isDebugPath = !!useRouteMatch(FLEET_ROUTING_PATHS.debug); useEffect(() => { (async () => { @@ -193,6 +194,10 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { ); } + // Debug page moved outside of initialization to allow debugging when setup failed + if (isDebugPath) { + return ; + } if (!isInitialized || initializationError) { return ( @@ -328,10 +333,6 @@ export const AppRoutes = memo( - - - - {/* TODO: Move this route to the Integrations app */} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/fleet_index_debugger.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/fleet_index_debugger.tsx index 3f678d4463480..f84468fb14738 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/fleet_index_debugger.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/fleet_index_debugger.tsx @@ -43,6 +43,8 @@ export const FleetIndexDebugger = () => { const indices = [ { label: '.fleet-agents', value: '.fleet-agents' }, { label: '.fleet-actions', value: '.fleet-actions' }, + { label: '.fleet-servers', value: '.fleet-servers' }, + { label: '.fleet-enrollment-api-keys', value: '.fleet-enrollment-api-keys' }, ]; const [index, setIndex] = useState(); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/health_check_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/health_check_panel.tsx new file mode 100644 index 0000000000000..5edd18716371c --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/health_check_panel.tsx @@ -0,0 +1,167 @@ +/* + * 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 React, { useEffect, useState, useMemo } from 'react'; + +import { + EuiSpacer, + EuiText, + EuiSuperSelect, + EuiFlexGroup, + EuiFlexItem, + EuiCallOut, + EuiHealth, +} from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n-react'; +import { useQuery } from '@tanstack/react-query'; + +import { sendPostHealthCheck, useGetFleetServerHosts } from '../../../hooks'; +import type { FleetServerHost } from '../../../types'; + +const POLLING_INTERVAL_S = 10; // 10 sec +const POLLING_INTERVAL_MS = POLLING_INTERVAL_S * 1000; + +export const HealthCheckPanel: React.FunctionComponent = () => { + const [selectedFleetServerHost, setSelectedFleetServerHost] = useState< + FleetServerHost | undefined + >(); + + const { data } = useGetFleetServerHosts(); + const fleetServerHosts = useMemo(() => data?.items ?? [], [data?.items]); + + useEffect(() => { + const defaultHost = fleetServerHosts.find((item) => item.is_default === true); + if (defaultHost) { + setSelectedFleetServerHost(defaultHost); + } + }, [fleetServerHosts]); + + const hostName = useMemo( + () => selectedFleetServerHost?.host_urls[0] || '', + [selectedFleetServerHost?.host_urls] + ); + + const [healthData, setHealthData] = useState(); + + const { data: healthCheckResponse } = useQuery( + ['fleetServerHealth', hostName], + () => sendPostHealthCheck({ host: hostName }), + { refetchInterval: POLLING_INTERVAL_MS } + ); + useEffect(() => { + setHealthData(healthCheckResponse); + }, [healthCheckResponse]); + + const fleetServerHostsOptions = useMemo( + () => [ + ...fleetServerHosts.map((fleetServerHost) => { + return { + inputDisplay: `${fleetServerHost.name} (${fleetServerHost.host_urls[0]})`, + value: fleetServerHost.id, + }; + }), + ], + [fleetServerHosts] + ); + + const healthStatus = (statusValue: string) => { + if (!statusValue) return null; + + let color; + switch (statusValue) { + case 'HEALTHY': + color = 'success'; + break; + case 'UNHEALTHY': + color = 'warning'; + break; + case 'OFFLINE': + color = 'subdued'; + break; + default: + color = 'subdued'; + } + + return {statusValue}; + }; + + return ( + <> + +

+ +

+
+ + + + + + + + } + onChange={(fleetServerHostId) => { + setHealthData(undefined); + setSelectedFleetServerHost( + fleetServerHosts.find((fleetServerHost) => fleetServerHost.id === fleetServerHostId) + ); + }} + valueOfSelected={selectedFleetServerHost?.id} + options={fleetServerHostsOptions} + /> + + + {healthData?.data?.status && hostName === healthData?.data?.host ? ( + + + + + {healthStatus(healthData?.data?.status)} + + ) : null} + + + {healthData?.error && ( + <> + + + {healthData?.error?.message ?? ( + + )} + + + )} + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/index.tsx index 6a89a696874a7..aeb2763d0e1c0 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/index.tsx @@ -11,3 +11,4 @@ export * from './saved_object_debugger'; export * from './preconfiguration_debugger'; export * from './fleet_index_debugger'; export * from './orphaned_integration_policy_debugger'; +export * from './health_check_panel'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/preconfiguration_debugger.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/preconfiguration_debugger.tsx index 8184242f99e8d..7642589bc1d6c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/preconfiguration_debugger.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/preconfiguration_debugger.tsx @@ -129,7 +129,7 @@ export const PreconfigurationDebugger: React.FunctionComponent = () => {

kibana.yml }} />

diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/saved_object_debugger.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/saved_object_debugger.tsx index de95b08a4dfb6..021608e4ef656 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/saved_object_debugger.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/components/saved_object_debugger.tsx @@ -22,6 +22,15 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { sendRequest } from '../../../hooks'; +import { + OUTPUT_SAVED_OBJECT_TYPE, + AGENT_POLICY_SAVED_OBJECT_TYPE, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, + PACKAGES_SAVED_OBJECT_TYPE, + DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE, + FLEET_SERVER_HOST_SAVED_OBJECT_TYPE, +} from '../../../../../../common/constants'; + import { CodeBlock } from './code_block'; import { SavedObjectNamesCombo } from './saved_object_names_combo'; @@ -61,29 +70,41 @@ const fetchSavedObjects = async (type?: string, name?: string) => { export const SavedObjectDebugger: React.FunctionComponent = () => { const types = [ { - value: 'ingest-agent-policies', + value: `${AGENT_POLICY_SAVED_OBJECT_TYPE}`, text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.agentPolicyLabel', { defaultMessage: 'Agent policy', }), }, { - value: 'ingest-package-policies', + value: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}`, text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.packagePolicyLabel', { defaultMessage: 'Integration policy', }), }, { - value: 'ingest-outputs', + value: `${OUTPUT_SAVED_OBJECT_TYPE}`, text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.outputLabel', { defaultMessage: 'Output', }), }, { - value: 'epm-packages', + value: `${PACKAGES_SAVED_OBJECT_TYPE}`, text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.packageLabel', { defaultMessage: 'Packages', }), }, + { + value: `${DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE}`, + text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.downloadSourceLabel', { + defaultMessage: 'Download Sources', + }), + }, + { + value: `${FLEET_SERVER_HOST_SAVED_OBJECT_TYPE}`, + text: i18n.translate('xpack.fleet.debug.savedObjectDebugger.fleetServerHostLabel', { + defaultMessage: 'Fleet Server Hosts', + }), + }, ]; const [type, setType] = useState(types[0].value); @@ -153,7 +174,7 @@ export const SavedObjectDebugger: React.FunctionComponent = () => { - {(status === 'error' || namesStatus === 'error') && ( + {savedObjectResult && (status === 'error' || namesStatus === 'error') && ( <> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/index.tsx index 89c61a78eb61c..7791575342c55 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/debug/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/debug/index.tsx @@ -14,6 +14,7 @@ import { EuiPage, EuiPageBody, EuiPageHeader, + EuiPageSection, EuiSpacer, EuiText, EuiTitle, @@ -24,6 +25,7 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { RequestError } from '../../hooks'; import { useLink, useStartServices } from '../../hooks'; import { @@ -33,6 +35,7 @@ import { FleetIndexDebugger, SavedObjectDebugger, OrphanedIntegrationPolicyDebugger, + HealthCheckPanel, } from './components'; // TODO: Evaluate moving this react-query initialization up to the main Fleet app @@ -40,6 +43,13 @@ import { export const queryClient = new QueryClient(); const panels = [ + { + title: i18n.translate('xpack.fleet.debug.HealthCheckStatus.title', { + defaultMessage: 'Health Check Status', + }), + id: 'healthCheckStatus', + component: , + }, { title: i18n.translate('xpack.fleet.debug.agentPolicyDebugger.title', { defaultMessage: 'Agent Policy Debugger', @@ -84,7 +94,10 @@ const panels = [ }, ]; -export const DebugPage: React.FunctionComponent = () => { +export const DebugPage: React.FunctionComponent<{ + isInitialized: boolean; + setupError: RequestError | null; +}> = ({ isInitialized, setupError }) => { const { chrome } = useStartServices(); const { getHref } = useLink(); @@ -92,93 +105,113 @@ export const DebugPage: React.FunctionComponent = () => { return ( - + - - - - - - - ), - strongLossOfData: ( - - - - ), - }} - /> - - + + + + + + + + + ), + strongLossOfData: ( + + + + ), + }} + /> + + + {!isInitialized && setupError?.message && ( + <> + + + + + + + + )} + - - - {panels.map(({ title, id, component }) => ( - <> - -

{title}

- - } - > - - {component} -
+ + + {panels.map(({ title, id, component }) => ( + <> + +

{title}

+ + } + > + + {component} +
- - - ))} + + + ))} - -

- -

-
+ +

+ +

+
- + - + +
diff --git a/x-pack/plugins/fleet/public/hooks/use_request/health_check.ts b/x-pack/plugins/fleet/public/hooks/use_request/health_check.ts new file mode 100644 index 0000000000000..c5fdc7886faac --- /dev/null +++ b/x-pack/plugins/fleet/public/hooks/use_request/health_check.ts @@ -0,0 +1,19 @@ +/* + * 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 type { PostHealthCheckRequest, PostHealthCheckResponse } from '../../types'; +import { appRoutesService } from '../../services'; + +import { sendRequest } from './use_request'; + +export function sendPostHealthCheck(body: PostHealthCheckRequest['body']) { + return sendRequest({ + method: 'post', + path: appRoutesService.postHealthCheckPath(), + body, + }); +} diff --git a/x-pack/plugins/fleet/public/hooks/use_request/index.ts b/x-pack/plugins/fleet/public/hooks/use_request/index.ts index 9ed23ef31c6a7..121ed9d3f8dd0 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/index.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/index.ts @@ -20,3 +20,4 @@ export * from './ingest_pipelines'; export * from './download_source'; export * from './fleet_server_hosts'; export * from './fleet_proxies'; +export * from './health_check'; diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 9cab8a0ddfa36..189f71138434c 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -129,6 +129,8 @@ export type { PostDownloadSourceRequest, PutDownloadSourceRequest, GetAvailableVersionsResponse, + PostHealthCheckRequest, + PostHealthCheckResponse, } from '../../common/types'; export { entries, diff --git a/x-pack/plugins/fleet/server/routes/health_check/index.ts b/x-pack/plugins/fleet/server/routes/health_check/index.ts index 23d917aa09a43..61b42b3bc2aa2 100644 --- a/x-pack/plugins/fleet/server/routes/health_check/index.ts +++ b/x-pack/plugins/fleet/server/routes/health_check/index.ts @@ -4,31 +4,67 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import https from 'https'; + +import type { TypeOf } from '@kbn/config-schema'; +import fetch from 'node-fetch'; import { APP_API_ROUTES } from '../../constants'; import type { FleetRequestHandler } from '../../types'; import type { FleetAuthzRouter } from '../security'; +import { defaultFleetErrorHandler } from '../../errors'; +import { PostHealthCheckRequestSchema } from '../../types'; export const registerRoutes = (router: FleetAuthzRouter) => { - router.get( + // get fleet server health check by host + router.post( { path: APP_API_ROUTES.HEALTH_CHECK_PATTERN, - validate: {}, + validate: PostHealthCheckRequestSchema, fleetAuthz: { fleet: { all: true }, }, }, - getHealthCheckHandler + postHealthCheckHandler ); }; -export const getHealthCheckHandler: FleetRequestHandler = async ( - context, - request, - response -) => { - return response.ok({ - body: 'Fleet Health Check Report:\nFleet Server: HEALTHY', - headers: { 'content-type': 'text/plain' }, - }); +export const postHealthCheckHandler: FleetRequestHandler< + undefined, + undefined, + TypeOf +> = async (context, request, response) => { + try { + const abortController = new AbortController(); + const { host } = request.body; + + // Sometimes when the host is not online, the request hangs + // Setting a timeout to abort the request after 5s + setTimeout(() => { + abortController.abort(); + }, 5000); + + const res = await fetch(`${host}/api/status`, { + headers: { + accept: '*/*', + }, + method: 'GET', + agent: new https.Agent({ + rejectUnauthorized: false, + }), + signal: abortController.signal, + }); + const bodyRes = await res.json(); + const body = { ...bodyRes, host }; + + return response.ok({ body }); + } catch (error) { + // when the request is aborted, return offline status + if (error.name === 'AbortError') { + return response.ok({ + body: { name: 'fleet-server', status: `OFFLINE`, host: request.body.host }, + }); + } + return defaultFleetErrorHandler({ error, response }); + } }; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/health_check.ts b/x-pack/plugins/fleet/server/types/rest_spec/health_check.ts new file mode 100644 index 0000000000000..8199a1b2c815a --- /dev/null +++ b/x-pack/plugins/fleet/server/types/rest_spec/health_check.ts @@ -0,0 +1,14 @@ +/* + * 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 { schema } from '@kbn/config-schema'; + +export const PostHealthCheckRequestSchema = { + body: schema.object({ + host: schema.uri({ scheme: ['http', 'https'] }), + }), +}; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/index.ts b/x-pack/plugins/fleet/server/types/rest_spec/index.ts index 066b780bd1d47..edbb6b7d7e816 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/index.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/index.ts @@ -20,3 +20,4 @@ export * from './setup'; export * from './check_permissions'; export * from './download_sources'; export * from './tags'; +export * from './health_check'; From c3038f439eaacadb78b1047782de769e904a6bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Mon, 5 Dec 2022 17:59:13 +0100 Subject: [PATCH 19/40] [APM] Add pagination to source map API (#145959) Closes https://github.com/elastic/kibana/issues/145884 Adds ability to paginate source map result via `page` and `perPage`. The request `GET /api/apm/sourcemaps?page=2&perPage=10`, will return: ```json { "artifacts": [], "total": 0 } ``` --- .../fleet/merge_package_policy_with_apm.ts | 7 +- .../apm/server/routes/fleet/source_maps.ts | 40 +++++++----- .../apm/server/routes/source_maps/route.ts | 24 +++++-- .../tests/sourcemaps/sourcemaps.ts | 65 +++++++++++++------ 4 files changed, 91 insertions(+), 45 deletions(-) diff --git a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts index 37f0705904770..1a3fcc6cd1967 100644 --- a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts +++ b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts @@ -12,7 +12,10 @@ import { getPackagePolicyWithAgentConfigurations, PackagePolicy, } from './register_fleet_policy_callbacks'; -import { getPackagePolicyWithSourceMap, listArtifacts } from './source_maps'; +import { + getPackagePolicyWithSourceMap, + listSourceMapArtifacts, +} from './source_maps'; export async function mergePackagePolicyWithApm({ packagePolicy, @@ -24,7 +27,7 @@ export async function mergePackagePolicyWithApm({ fleetPluginStart: NonNullable; }) { const agentConfigurations = await listConfigurations(internalESClient); - const artifacts = await listArtifacts({ fleetPluginStart }); + const { artifacts } = await listSourceMapArtifacts({ fleetPluginStart }); return getPackagePolicyWithAgentConfigurations( getPackagePolicyWithSourceMap({ packagePolicy, artifacts }), agentConfigurations diff --git a/x-pack/plugins/apm/server/routes/fleet/source_maps.ts b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts index 6000b79956665..9cba744cdb689 100644 --- a/x-pack/plugins/apm/server/routes/fleet/source_maps.ts +++ b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts @@ -32,37 +32,44 @@ export type FleetPluginStart = NonNullable; const doUnzip = promisify(unzip); -function decodeArtifacts(artifacts: Artifact[]): Promise { - return Promise.all( - artifacts.map(async (artifact) => { - const body = await doUnzip(Buffer.from(artifact.body, 'base64')); - return { - ...artifact, - body: JSON.parse(body.toString()) as ApmArtifactBody, - }; - }) - ); +async function unzipArtifactBody( + artifact: Artifact +): Promise { + const body = await doUnzip(Buffer.from(artifact.body, 'base64')); + + return { + ...artifact, + body: JSON.parse(body.toString()) as ApmArtifactBody, + }; } function getApmArtifactClient(fleetPluginStart: FleetPluginStart) { return fleetPluginStart.createArtifactsClient('apm'); } -export async function listArtifacts({ +export async function listSourceMapArtifacts({ fleetPluginStart, + perPage = 20, + page = 1, }: { fleetPluginStart: FleetPluginStart; + perPage?: number; + page?: number; }) { const apmArtifactClient = getApmArtifactClient(fleetPluginStart); - const fleetArtifactsResponse = await apmArtifactClient.listArtifacts({ + const artifactsResponse = await apmArtifactClient.listArtifacts({ kuery: 'type: sourcemap', - perPage: 20, - page: 1, + perPage, + page, sortOrder: 'desc', sortField: 'created', }); - return decodeArtifacts(fleetArtifactsResponse.items); + const artifacts = await Promise.all( + artifactsResponse.items.map(unzipArtifactBody) + ); + + return { artifacts, total: artifactsResponse.total }; } export async function createApmArtifact({ @@ -141,8 +148,7 @@ export async function updateSourceMapsOnFleetPolicies({ savedObjectsClient: SavedObjectsClientContract; elasticsearchClient: ElasticsearchClient; }) { - const artifacts = await listArtifacts({ fleetPluginStart }); - + const { artifacts } = await listSourceMapArtifacts({ fleetPluginStart }); const apmFleetPolicies = await getApmPackagePolicies({ core, fleetPluginStart, diff --git a/x-pack/plugins/apm/server/routes/source_maps/route.ts b/x-pack/plugins/apm/server/routes/source_maps/route.ts index 738192377beb0..b4d005373c4be 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/route.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/route.ts @@ -7,12 +7,12 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; import { SavedObjectsClientContract } from '@kbn/core/server'; -import { jsonRt } from '@kbn/io-ts-utils'; +import { jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import { Artifact } from '@kbn/fleet-plugin/server'; import { createApmArtifact, deleteApmArtifact, - listArtifacts, + listSourceMapArtifacts, updateSourceMapsOnFleetPolicies, getCleanedBundleFilePath, ArtifactSourceMap, @@ -40,14 +40,28 @@ export type SourceMap = t.TypeOf; const listSourceMapRoute = createApmServerRoute({ endpoint: 'GET /api/apm/sourcemaps', options: { tags: ['access:apm'] }, + params: t.partial({ + query: t.partial({ + page: toNumberRt, + perPage: toNumberRt, + }), + }), async handler({ + params, plugins, - }): Promise<{ artifacts: ArtifactSourceMap[] } | undefined> { + }): Promise<{ artifacts: ArtifactSourceMap[]; total: number } | undefined> { + const { page, perPage } = params.query; + try { const fleetPluginStart = await plugins.fleet?.start(); if (fleetPluginStart) { - const artifacts = await listArtifacts({ fleetPluginStart }); - return { artifacts }; + const { artifacts, total } = await listSourceMapArtifacts({ + fleetPluginStart, + page, + perPage, + }); + + return { artifacts, total }; } } catch (e) { throw Boom.internal( diff --git a/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts b/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts index 44a9eae45b5f1..0b3dbf2c6ebfc 100644 --- a/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts +++ b/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts @@ -7,7 +7,7 @@ import { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; import type { SourceMap } from '@kbn/apm-plugin/server/routes/source_maps/route'; import expect from '@kbn/expect'; -import { times } from 'lodash'; +import { first, last, times } from 'lodash'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function ApiTest({ getService }: FtrProviderContext) { @@ -47,11 +47,14 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); } - async function listSourcemaps() { + async function listSourcemaps({ page, perPage }: { page?: number; perPage?: number } = {}) { + const query = page && perPage ? { page, perPage } : {}; + const response = await apmApiClient.readUser({ endpoint: 'GET /api/apm/sourcemaps', + params: { query }, }); - return response.body.artifacts; + return response.body; } registry.when('source maps', { config: 'basic', archives: [] }, () => { @@ -66,7 +69,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('can upload a source map', async () => { resp = await uploadSourcemap({ - serviceName: 'foo', + serviceName: 'my_service', serviceVersion: '1.0.0', bundleFilePath: 'bar', sourcemap: { @@ -79,13 +82,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); - describe('list source maps', () => { + describe('list source maps', async () => { const uploadedSourcemapIds: string[] = []; before(async () => { - const sourcemapCount = times(2); + const sourcemapCount = times(15); for (const i of sourcemapCount) { const sourcemap = await uploadSourcemap({ - serviceName: 'foo', + serviceName: 'my_service', serviceVersion: `1.0.${i}`, bundleFilePath: 'bar', sourcemap: { @@ -95,7 +98,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); uploadedSourcemapIds.push(sourcemap.id); - await sleep(100); } }); @@ -103,17 +105,41 @@ export default function ApiTest({ getService }: FtrProviderContext) { await Promise.all(uploadedSourcemapIds.map((id) => deleteSourcemap(id))); }); + describe('pagination', () => { + it('can retrieve the first page', async () => { + const firstPageItems = await listSourcemaps({ page: 1, perPage: 5 }); + expect(first(firstPageItems.artifacts)?.identifier).to.eql('my_service-1.0.14'); + expect(last(firstPageItems.artifacts)?.identifier).to.eql('my_service-1.0.10'); + expect(firstPageItems.artifacts.length).to.be(5); + expect(firstPageItems.total).to.be(15); + }); + + it('can retrieve the second page', async () => { + const secondPageItems = await listSourcemaps({ page: 2, perPage: 5 }); + expect(first(secondPageItems.artifacts)?.identifier).to.eql('my_service-1.0.9'); + expect(last(secondPageItems.artifacts)?.identifier).to.eql('my_service-1.0.5'); + expect(secondPageItems.artifacts.length).to.be(5); + expect(secondPageItems.total).to.be(15); + }); + + it('can retrieve the third page', async () => { + const thirdPageItems = await listSourcemaps({ page: 3, perPage: 5 }); + expect(first(thirdPageItems.artifacts)?.identifier).to.eql('my_service-1.0.4'); + expect(last(thirdPageItems.artifacts)?.identifier).to.eql('my_service-1.0.0'); + expect(thirdPageItems.artifacts.length).to.be(5); + expect(thirdPageItems.total).to.be(15); + }); + }); + it('can list source maps', async () => { const sourcemaps = await listSourcemaps(); - expect(sourcemaps).to.not.empty(); + expect(sourcemaps.artifacts.length).to.be(15); + expect(sourcemaps.total).to.be(15); }); it('returns newest source maps first', async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /api/apm/sourcemaps', - }); - - const timestamps = response.body.artifacts.map((a) => new Date(a.created).getTime()); + const { artifacts } = await listSourcemaps(); + const timestamps = artifacts.map((a) => new Date(a.created).getTime()); expect(timestamps[0]).to.be.greaterThan(timestamps[1]); }); }); @@ -121,7 +147,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { describe('delete source maps', () => { it('can delete a source map', async () => { const sourcemap = await uploadSourcemap({ - serviceName: 'foo', + serviceName: 'my_service', serviceVersion: '1.0.0', bundleFilePath: 'bar', sourcemap: { @@ -132,13 +158,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); await deleteSourcemap(sourcemap.id); - const sourcemaps = await listSourcemaps(); - expect(sourcemaps).to.be.empty(); + const { artifacts, total } = await listSourcemaps(); + expect(artifacts).to.be.empty(); + expect(total).to.be(0); }); }); }); } - -function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} From 91db82a055cabe4f83e6bc38e93d5a80f8eb9da1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 10:21:39 -0700 Subject: [PATCH 20/40] Update dependency @elastic/charts to v51 (main) (#145286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@elastic/charts](https://togithub.com/elastic/elastic-charts) | [`50.2.1` -> `51.1.0`](https://renovatebot.com/diffs/npm/@elastic%2fcharts/50.2.1/51.1.0) | [![age](https://badges.renovateapi.com/packages/npm/@elastic%2fcharts/51.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@elastic%2fcharts/51.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@elastic%2fcharts/51.1.0/compatibility-slim/50.2.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@elastic%2fcharts/51.1.0/confidence-slim/50.2.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/elastic/kibana). ## Notes for Uptime team As defined with @awahab07 I've updated the current Monitor status custom tooltip to follow a bit more the principles of the tooltip components. The style is slightly changed but not much. This will allow us to continue iterating on improving such components and having an aligned style across visualizations Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: nickofthyme Co-authored-by: Nick Partridge Co-authored-by: Marco Vettorello Co-authored-by: Stratoula Kalafateli --- package.json | 2 +- .../monitor_status_cell_tooltip.tsx | 119 +++++++----------- .../__snapshots__/donut_chart.test.tsx.snap | 14 +++ yarn.lock | 15 ++- 4 files changed, 68 insertions(+), 82 deletions(-) diff --git a/package.json b/package.json index 20613741aa8e6..2f5d7a6349f14 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@dnd-kit/utilities": "^2.0.0", "@elastic/apm-rum": "^5.12.0", "@elastic/apm-rum-react": "^1.4.2", - "@elastic/charts": "50.2.1", + "@elastic/charts": "51.1.1", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.5.0-canary.1", "@elastic/ems-client": "8.3.3", diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx index 8aa155dd2df7b..04505a90628aa 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx @@ -7,24 +7,15 @@ import React from 'react'; import moment from 'moment'; -import { css } from '@emotion/react'; -import { useEuiTheme, EuiText, EuiProgress } from '@elastic/eui'; +import { EuiProgress } from '@elastic/eui'; -import { - TooltipTable, - TooltipTableBody, - TooltipHeader, - TooltipDivider, - TooltipTableRow, - TooltipTableCell, -} from '@elastic/charts'; +import { TooltipTable, TooltipHeader, TooltipValue } from '@elastic/charts'; import { usePingStatusesIsLoading } from '../hooks/use_ping_statuses'; import { MonitorStatusTimeBin, SUCCESS_VIZ_COLOR, DANGER_VIZ_COLOR } from './monitor_status_data'; import * as labels from './labels'; export const MonitorStatusCellTooltip = ({ timeBin }: { timeBin?: MonitorStatusTimeBin }) => { - const { euiTheme } = useEuiTheme(); const isLoading = usePingStatusesIsLoading(); if (!timeBin) { @@ -47,74 +38,50 @@ export const MonitorStatusCellTooltip = ({ timeBin }: { timeBin?: MonitorStatusT ? `${Math.round((timeBin.ups / (timeBin.ups + timeBin.downs)) * 100)}%` : '-'; - return ( - <> - - - {tooltipTitle} - - - - {isLoading ? : } - -
- - - - - - - - - - - - - -
- - ); -}; - -const TooltipListRow = ({ - color, - label, - value, -}: { - color?: string; - label: string; - value: string; -}) => { - const { euiTheme } = useEuiTheme(); + // not currently used but required by current types + const commonTooltipValuesProps = { + isVisible: true, + isHighlighted: false, + seriesIdentifier: { specId: '', key: '' }, + }; + const tooltipValues: TooltipValue[] = isLoading + ? [] + : [ + { + color: 'transparent', + label: labels.AVAILABILITY_LABEL, + value: availabilityStr, + formattedValue: availabilityStr, + ...commonTooltipValuesProps, + }, + { + color: SUCCESS_VIZ_COLOR, + label: labels.COMPLETE_LABEL, + value: timeBin.ups, + formattedValue: `${timeBin.ups}`, + ...commonTooltipValuesProps, + }, + { + color: DANGER_VIZ_COLOR, + label: labels.FAILED_LABEL, + value: timeBin.downs, + formattedValue: `${timeBin.downs}`, + ...commonTooltipValuesProps, + }, + ]; return ( <> - - {label} - - - - - {value} - - + {tooltipTitle} + {isLoading && } + t.label, style: { textAlign: 'left' } }, + { type: 'number', cell: (t) => t.value, style: { textAlign: 'right' } }, + ]} + items={tooltipValues} + /> ); }; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap index 4a23e885b8f13..9cd19cb2404de 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap @@ -377,6 +377,15 @@ exports[`DonutChart component passes correct props without errors for valid prop "width": "auto", }, }, + "highlighter": Object { + "point": Object { + "fill": "__use__empty__color__", + "opacity": 1, + "radius": 10, + "stroke": "__use__series__color__", + "strokeWidth": 4, + }, + }, "legend": Object { "horizontalHeight": 64, "labelOptions": Object { @@ -490,6 +499,11 @@ exports[`DonutChart component passes correct props without errors for valid prop "opacity": 0.25, }, }, + "tooltip": Object { + "defaultDotColor": "black", + "maxTableHeight": 120, + "maxWidth": 260, + }, } } theme={ diff --git a/yarn.lock b/yarn.lock index fa62aa0fc81c3..a0b8800f50d46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1452,10 +1452,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@50.2.1": - version "50.2.1" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-50.2.1.tgz#3dde69125fb181306129a48b73bce1f5823d0cad" - integrity sha512-LA9EcW1LGAIrlhro3P2Fgtj0BkHQV1ArHCEdJ43EjgaNpJsKaWnFSeYcbuXiUEyLtXbF4Sv6Di90qDppwThu6Q== +"@elastic/charts@51.1.1": + version "51.1.1" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-51.1.1.tgz#005c9fce7a2ef0345ac223d18115ad719c2c15e2" + integrity sha512-DJjhHBvovQ/EfAlF7cjAB1fhwjcrt4Iyy/Vxed0BAw6gqoppT7/3Kk8AmUzzj05BK7ZFHlaL/05fe3fUEWuQEw== dependencies: "@popperjs/core" "^2.4.0" bezier-easing "^2.1.0" @@ -1476,7 +1476,7 @@ resize-observer-polyfill "^1.5.1" ts-debounce "^4.0.0" utility-types "^3.10.0" - uuid "^8.3.2" + uuid "^9" "@elastic/datemath@5.0.3": version "5.0.3" @@ -27011,6 +27011,11 @@ uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" From f7b74d0c4ee1f17af350c89f6507a4a23719bac1 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 5 Dec 2022 17:37:09 +0000 Subject: [PATCH 21/40] [ML] Fixing model testing with index field selection (#146862) Fixes issue where changing the selected field or pressing the reload examples button causes the default field name to be added to the pipeline. The inference still works as the field is also renamed in the supplied docs. but it does mean the pipeline doesn't really match the real index field name and so can't be used to ingest data. The fix is to ensure `inferrer.setInputField(..)` is called whenever the field select changes or examples are reloaded. --- .../test_models/models/index_input.tsx | 23 +++++++++++-------- .../test_models/models/inference_base.ts | 6 ++++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/index_input.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/index_input.tsx index 49c9b2ef62c06..484515f4a59cf 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/index_input.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/index_input.tsx @@ -103,8 +103,12 @@ export function useIndexInput({ inferrer }: { inferrer: InferrerType }) { const [selectedDataViewId, setSelectedDataViewId] = useState(undefined); const [selectedDataView, setSelectedDataView] = useState(null); const [fieldNames, setFieldNames] = useState>([]); - const [selectedField, setSelectedField] = useState(undefined); + const selectedField = useObservable(inferrer.getInputField$(), inferrer.getInputField()); + const setSelectedField = useCallback( + (fieldName: string) => inferrer.setInputField(fieldName), + [inferrer] + ); useEffect( function loadDataViewListItems() { dataViews.getIdsWithTitle().then((items) => { @@ -122,7 +126,6 @@ export function useIndexInput({ inferrer }: { inferrer: InferrerType }) { function loadSelectedDataView() { inferrer.reset(); setFieldNames([]); - setSelectedField(undefined); if (selectedDataViewId !== undefined) { dataViews.get(selectedDataViewId).then((dv) => setSelectedDataView(dv)); } @@ -158,14 +161,14 @@ export function useIndexInput({ inferrer }: { inferrer: InferrerType }) { inferrer.setInputText(tempExamples); }); } - }, [inferrer, selectedField, selectedDataView, search]); + }, [inferrer, selectedDataView, search, selectedField]); useEffect( function loadFieldNames() { if (selectedDataView !== null) { const tempFieldNames = selectedDataView.fields .filter( - ({ displayName, esTypes, count }) => + ({ displayName, esTypes }) => esTypes && esTypes.includes('text') && !['_id', '_index'].includes(displayName) ) .sort((a, b) => a.displayName.localeCompare(b.displayName)) @@ -174,11 +177,9 @@ export function useIndexInput({ inferrer }: { inferrer: InferrerType }) { text: displayName, })); setFieldNames(tempFieldNames); - if (tempFieldNames.length === 1) { - const fieldName = tempFieldNames[0].value; - setSelectedField(fieldName); - inferrer.setInputField(fieldName); - } + + const fieldName = tempFieldNames.length === 1 ? tempFieldNames[0].value : undefined; + inferrer.setInputField(fieldName); } }, [selectedDataView, inferrer] @@ -188,7 +189,9 @@ export function useIndexInput({ inferrer }: { inferrer: InferrerType }) { function loadExamplesAfterFieldChange() { loadExamples(); }, - [selectedField, loadExamples] + // only load examples if selectedField changes + // eslint-disable-next-line react-hooks/exhaustive-deps + [selectedField] ); function reloadExamples() { diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/inference_base.ts b/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/inference_base.ts index eba9a92e77549..28b3073cfbb14 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/inference_base.ts +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/test_models/models/inference_base.ts @@ -151,7 +151,6 @@ export abstract class InferenceBase { } public reset() { - this.setInputField(undefined); this.inputText$.next([]); this.inferenceResult$.next(null); this.inferenceError$.next(null); @@ -159,6 +158,7 @@ export abstract class InferenceBase { } public setInputField(field: string | undefined) { + // if the field is not set, change to be the same as the model input field this.inputField$.next(field === undefined ? this.modelInputField : field); } @@ -166,6 +166,10 @@ export abstract class InferenceBase { return this.inputField$.getValue(); } + public getInputField$() { + return this.inputField$.asObservable(); + } + public setInputText(text: string[]) { this.inputText$.next(text); } From 83657cd537e7f858b9c2238e9e90a2de48178b65 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 5 Dec 2022 18:48:03 +0100 Subject: [PATCH 22/40] [ResponseOps] [Cases] UX enhancements (#146608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #144614 ## Summary Case Detail Page - The ‘Add comment’ button in the Case detail page is now disabled until a comment is filled in. - The save button in the 'Edit Comment' section of the Case detail page is now disabled if a comment is empty. - The Tags in the activity stream now display a hollow badge equal to the ones on the sidebar. - Fixed the spacing between the headings in the sidebar. The gutter size was increased. Case Creation Page - The Create and Cancel buttons were too close together. The distance between them was increased. - There is now a confirmation dialog if the user clicks the cancel button. - Introduced a restricted page width. The max is now 1200px. All Cases list - Brought back the distance between tags in the rows ### Screenshots
Disabled Add comment buttonScreenshot 2022-11-29 at 19 04 25
Enabled Add comment buttonScreenshot 2022-11-29 at 19 04 34
Hollow tagsScreenshot
2022-11-29 at 19 03 33
Fixed sidebar spacingScreenshot 2022-11-28 at 12 11 52
Create and Cancel button spacingScreenshot 2022-11-29 at 19 05 54
Cancel create case confirmation dialogScreenshot 2022-11-29 at 19 06 03
Centered, restricted page widthScreenshot 2022-11-28 at 14 58 34
Margin between tagsScreenshot 2022-12-02 at 10 59 26
--- .../cases/public/common/translations.ts | 9 +- .../public/components/add_comment/index.tsx | 2 +- .../public/components/add_comment/schema.tsx | 3 +- .../all_cases/use_cases_columns.tsx | 5 +- .../components/case_view_activity.tsx | 2 +- ...ancel_creation_confirmation_modal.test.tsx | 55 +++++++++++ .../cancel_creation_confirmation_modal.tsx | 41 ++++++++ .../cases/public/components/create/form.tsx | 94 +++++++++++-------- .../public/components/create/index.test.tsx | 62 +++++++++++- .../cases/public/components/create/index.tsx | 5 +- .../public/components/create/translations.ts | 12 +++ .../use_cancel_creation_action.test.tsx | 78 +++++++++++++++ .../create/use_cancel_creation_action.tsx | 31 ++++++ .../user_actions/markdown_form.test.tsx | 24 +++++ .../components/user_actions/markdown_form.tsx | 42 ++------- .../user_actions/markdown_form_footer.tsx | 57 +++++++++++ .../public/components/user_actions/tags.tsx | 2 +- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../page_objects/observability_page.ts | 2 + 21 files changed, 438 insertions(+), 91 deletions(-) create mode 100644 x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.test.tsx create mode 100644 x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx create mode 100644 x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx create mode 100644 x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx create mode 100644 x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index 08f7c0aa4e8d0..d46734524cb25 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -70,9 +70,12 @@ export const ARIA_KEYPAD_LEGEND = i18n.translate( } ); -export const COMMENT_REQUIRED = i18n.translate('xpack.cases.caseView.commentFieldRequiredError', { - defaultMessage: 'A comment is required.', -}); +export const EMPTY_COMMENTS_NOT_ALLOWED = i18n.translate( + 'xpack.cases.caseView.commentFieldRequiredError', + { + defaultMessage: 'Empty comments are not allowed.', + } +); export const REQUIRED_FIELD = i18n.translate('xpack.cases.caseView.fieldRequiredError', { defaultMessage: 'Required field', diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index dc5c1c48cfd9b..57dccbbfebe4e 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -177,7 +177,7 @@ export const AddComment = React.memo( data-test-subj="submit-comment" fill iconType="plusInCircle" - isDisabled={isLoading} + isDisabled={!comment || isLoading} isLoading={isLoading} onClick={onSubmit} > diff --git a/x-pack/plugins/cases/public/components/add_comment/schema.tsx b/x-pack/plugins/cases/public/components/add_comment/schema.tsx index 5df5769ef62ab..980a03e76b772 100644 --- a/x-pack/plugins/cases/public/components/add_comment/schema.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/schema.tsx @@ -9,6 +9,7 @@ import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { CommentRequestUserType } from '../../../common/api'; + import * as i18n from './translations'; const { emptyField } = fieldValidators; @@ -22,7 +23,7 @@ export const schema: FormSchema = { type: FIELD_TYPES.TEXTAREA, validations: [ { - validator: emptyField(i18n.COMMENT_REQUIRED), + validator: emptyField(i18n.EMPTY_COMMENTS_NOT_ALLOWED), }, ], }, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx index cb08bf4b6e526..df261b613b0b2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx @@ -65,8 +65,11 @@ const LineClampedEuiBadgeGroup = euiStyled(EuiBadgeGroup)` word-break: normal; `; +// margin-right is required here because -webkit-box-orient: vertical; +// in the EuiBadgeGroup prevents us from defining gutterSize. const StyledEuiBadge = euiStyled(EuiBadge)` - max-width: 100px + max-width: 100px; + margin-right: 5px; `; // to allow for ellipsis const renderStringField = (field: string, dataTestSubj: string) => diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index 1fa5e94e6df98..dc1db2651f5bf 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -189,7 +189,7 @@ export const CaseViewActivity = ({ )} - + {caseAssignmentAuthorized ? ( <> { + let appMock: AppMockRenderer; + const props = { + title: 'My title', + confirmButtonText: 'My confirm button text', + cancelButtonText: 'My cancel button text', + onCancel: jest.fn(), + onConfirm: jest.fn(), + }; + + beforeEach(() => { + appMock = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('renders correctly', async () => { + const result = appMock.render(); + + expect(result.getByTestId('cancel-creation-confirmation-modal')).toBeInTheDocument(); + expect(result.getByText(props.title)).toBeInTheDocument(); + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + }); + + it('calls onConfirm', async () => { + const result = appMock.render(); + + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.confirmButtonText)); + + expect(props.onConfirm).toHaveBeenCalled(); + }); + + it('calls onCancel', async () => { + const result = appMock.render(); + + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.cancelButtonText)); + + expect(props.onCancel).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx new file mode 100644 index 0000000000000..0f73d90a60986 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx @@ -0,0 +1,41 @@ +/* + * 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 React from 'react'; +import type { EuiConfirmModalProps } from '@elastic/eui'; +import { EuiConfirmModal } from '@elastic/eui'; +import * as i18n from './translations'; + +type Props = Pick< + EuiConfirmModalProps, + 'title' | 'confirmButtonText' | 'cancelButtonText' | 'onConfirm' | 'onCancel' +>; + +const CancelCreationConfirmationModalComponent: React.FC = ({ + title, + confirmButtonText = i18n.CONFIRM_MODAL_BUTTON, + cancelButtonText = i18n.CANCEL_MODAL_BUTTON, + onConfirm, + onCancel, +}) => { + return ( + + ); +}; + +CancelCreationConfirmationModalComponent.displayName = 'CancelCreationConfirmationModal'; + +export const CancelCreationConfirmationModal = React.memo(CancelCreationConfirmationModalComponent); diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 4ec587667e18d..68ec55bbc956b 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -38,6 +38,8 @@ import { useAvailableCasesOwners } from '../app/use_available_owners'; import type { CaseAttachmentsWithoutOwner } from '../../types'; import { Severity } from './severity'; import { Assignees } from './assignees'; +import { useCancelCreationAction } from './use_cancel_creation_action'; +import { CancelCreationConfirmationModal } from './cancel_creation_confirmation_modal'; interface ContainerProps { big?: boolean; @@ -184,45 +186,59 @@ export const CreateCaseForm: React.FC = React.memo( timelineIntegration, attachments, initialValue, - }) => ( - - - - - - - - {i18n.CANCEL} - - - - - - - - - - - ) + }) => { + const { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal } = + useCancelCreationAction({ + onConfirmationCallback: onCancel, + }); + + return ( + + + + + + + + {i18n.CANCEL} + + {showConfirmationModal && ( + + )} + + + + + + + + + + ); + } ); CreateCaseForm.displayName = 'CreateCaseForm'; diff --git a/x-pack/plugins/cases/public/components/create/index.test.tsx b/x-pack/plugins/cases/public/components/create/index.test.tsx index bd2ef3ca1068f..24798c114fede 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { ReactWrapper } from 'enzyme'; import { mount } from 'enzyme'; -import { act } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; + import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; @@ -105,16 +106,66 @@ describe('CreateCase case', () => { }); }); - it('should call cancel on cancel click', async () => { + it('should open modal on cancel click', async () => { const wrapper = mount( ); - await act(async () => { - wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + }); + + it('should confirm cancelation on modal confirm click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalConfirmButton"]`).simulate('click'); + + await waitFor(() => { + expect(defaultProps.onCancel).toHaveBeenCalled(); + }); + }); + + it('should close modal on modal cancel click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalCancelButton"]`).simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeFalsy(); }); - expect(defaultProps.onCancel).toHaveBeenCalled(); }); it('should redirect to new case when posting the case', async () => { @@ -128,6 +179,7 @@ describe('CreateCase case', () => { fillForm(wrapper); wrapper.find(`button[data-test-subj="create-case-submit"]`).first().simulate('click'); }); + expect(defaultProps.onSuccess).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index 386b64f04bd1c..a765bb0f7b801 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { EuiPageSection } from '@elastic/eui'; import * as i18n from './translations'; import type { CreateCaseFormProps } from './form'; import { CreateCaseForm } from './form'; @@ -23,7 +24,7 @@ export const CreateCase = React.memo( useCasesBreadcrumbs(CasesDeepLinkId.casesCreate); return ( - <> + ( timelineIntegration={timelineIntegration} withSteps={withSteps} /> - + ); } ); diff --git a/x-pack/plugins/cases/public/components/create/translations.ts b/x-pack/plugins/cases/public/components/create/translations.ts index 780a1bbd1d02f..4bb7471e1c648 100644 --- a/x-pack/plugins/cases/public/components/create/translations.ts +++ b/x-pack/plugins/cases/public/components/create/translations.ts @@ -29,3 +29,15 @@ export const SYNC_ALERTS_LABEL = i18n.translate('xpack.cases.create.syncAlertsLa export const ASSIGN_YOURSELF = i18n.translate('xpack.cases.create.assignYourself', { defaultMessage: 'Assign yourself', }); + +export const MODAL_TITLE = i18n.translate('xpack.cases.create.modalTitle', { + defaultMessage: 'Discard case?', +}); + +export const CANCEL_MODAL_BUTTON = i18n.translate('xpack.cases.create.cancelModalButton', { + defaultMessage: 'Cancel', +}); + +export const CONFIRM_MODAL_BUTTON = i18n.translate('xpack.cases.create.confirmModalButton', { + defaultMessage: 'Exit without saving', +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx new file mode 100644 index 0000000000000..4174d33c44d2f --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx @@ -0,0 +1,78 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import { useCancelCreationAction } from './use_cancel_creation_action'; + +describe('UseConfirmationModal', () => { + let appMockRender: AppMockRenderer; + const onConfirmationCallback = jest.fn(); + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('init', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('opens the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + }); + + it('closes the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onCancelModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('calls onConfirmationCallback on confirm', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onConfirmModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + expect(onConfirmationCallback).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx new file mode 100644 index 0000000000000..461125b739ee7 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx @@ -0,0 +1,31 @@ +/* + * 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, useState } from 'react'; + +interface Props { + onConfirmationCallback: () => void; +} + +export const useCancelCreationAction = ({ onConfirmationCallback }: Props) => { + const [showConfirmationModal, setShowConfirmationModal] = useState(false); + + const onOpenModal = useCallback(() => { + setShowConfirmationModal(true); + }, []); + + const onConfirmModal = useCallback(() => { + setShowConfirmationModal(false); + onConfirmationCallback(); + }, [onConfirmationCallback]); + + const onCancelModal = useCallback(() => { + setShowConfirmationModal(false); + }, []); + + return { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal }; +}; diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx index f9fb8594ea51e..c6b6c0e59f004 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx @@ -16,6 +16,7 @@ const onChangeEditable = jest.fn(); const onSaveContent = jest.fn(); const newValue = 'Hello from Tehas'; +const emptyValue = ''; const hyperlink = `[hyperlink](http://elastic.co)`; const defaultProps = { content: `A link to a timeline ${hyperlink}`, @@ -61,6 +62,7 @@ describe('UserActionMarkdown ', () => { expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); }); }); + it('Does not call onSaveContent if no change from current text', async () => { const wrapper = mount( @@ -75,6 +77,28 @@ describe('UserActionMarkdown ', () => { }); expect(onSaveContent).not.toHaveBeenCalled(); }); + + it('Save button disabled if current text is empty', async () => { + const wrapper = mount( + + + + ); + + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: emptyValue }, + }); + + await waitFor(() => { + expect( + wrapper.find(`button[data-test-subj="user-action-save-markdown"]`).first().prop('disabled') + ).toBeTruthy(); + }); + }); + it('Cancel button click calls only onChangeEditable', async () => { const wrapper = mount( diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx index b2b7443e001e8..42abc55f336c9 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx @@ -5,15 +5,14 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; -import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from 'react'; +import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; import styled from 'styled-components'; import { Form, useForm, UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import * as i18n from '../case_view/translations'; import type { Content } from './schema'; import { schema } from './schema'; import { MarkdownRenderer, MarkdownEditorForm } from '../markdown_editor'; +import { UserActionMarkdownFooter } from './markdown_form_footer'; export const ContentWrapper = styled.div` padding: ${({ theme }) => `${theme.eui.euiSizeM} ${theme.eui.euiSizeL}`}; @@ -66,36 +65,6 @@ const UserActionMarkdownComponent = forwardRef< [setFieldValue] ); - const EditorButtons = useMemo( - () => ( - - - - {i18n.CANCEL} - - - - - {i18n.SAVE} - - - - ), - [handleCancelAction, handleSaveAction] - ); - useImperativeHandle(ref, () => ({ setComment, editor: editorRef.current, @@ -111,7 +80,12 @@ const UserActionMarkdownComponent = forwardRef< 'aria-label': 'Cases markdown editor', value: content, id, - bottomRightContent: EditorButtons, + bottomRightContent: ( + + ), }} /> diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx new file mode 100644 index 0000000000000..ad047c68313f1 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx @@ -0,0 +1,57 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; +import React from 'react'; + +import { useFormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; + +import * as i18n from '../case_view/translations'; + +interface UserActionMarkdownFooterProps { + handleSaveAction: () => Promise; + handleCancelAction: () => void; +} + +const UserActionMarkdownFooterComponent: React.FC = ({ + handleSaveAction, + handleCancelAction, +}) => { + const [{ content }] = useFormData<{ content: string }>({ watch: ['content'] }); + + return ( + + + + {i18n.CANCEL} + + + + + {i18n.SAVE} + + + + ); +}; + +UserActionMarkdownFooterComponent.displayName = 'UserActionMarkdownFooterComponent'; + +export const UserActionMarkdownFooter = React.memo(UserActionMarkdownFooterComponent); diff --git a/x-pack/plugins/cases/public/components/user_actions/tags.tsx b/x-pack/plugins/cases/public/components/user_actions/tags.tsx index bbcad0e8486f5..ad944f1cf49b1 100644 --- a/x-pack/plugins/cases/public/components/user_actions/tags.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/tags.tsx @@ -25,7 +25,7 @@ const getLabelTitle = (userAction: UserActionResponse) => { {userAction.action === Actions.delete && i18n.REMOVED_FIELD} {i18n.TAGS.toLowerCase()} - + ); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index f5fac7b6b4459..b2746c0c2fd82 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -9278,7 +9278,6 @@ "xpack.cases.caseView.comment": "commentaire", "xpack.cases.caseView.comment.addComment": "Ajouter un commentaire", "xpack.cases.caseView.comment.addCommentHelpText": "Ajouter un nouveau commentaire...", - "xpack.cases.caseView.commentFieldRequiredError": "Un commentaire est requis.", "xpack.cases.caseView.connectors": "Système de gestion des incidents externes", "xpack.cases.caseView.copyCommentLinkAria": "Copier le lien de référence", "xpack.cases.caseView.create": "Créer un cas", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 26cb9a3bc6f06..245b2a33195fe 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9265,7 +9265,6 @@ "xpack.cases.caseView.comment": "コメント", "xpack.cases.caseView.comment.addComment": "コメントを追加", "xpack.cases.caseView.comment.addCommentHelpText": "新しいコメントを追加...", - "xpack.cases.caseView.commentFieldRequiredError": "コメントが必要です。", "xpack.cases.caseView.connectors": "外部インシデント管理システム", "xpack.cases.caseView.copyCommentLinkAria": "参照リンクをコピー", "xpack.cases.caseView.create": "ケースを作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b184a4daf8113..87b560ac76f5c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9283,7 +9283,6 @@ "xpack.cases.caseView.comment": "注释", "xpack.cases.caseView.comment.addComment": "添加注释", "xpack.cases.caseView.comment.addCommentHelpText": "添加新注释......", - "xpack.cases.caseView.commentFieldRequiredError": "注释必填。", "xpack.cases.caseView.connectors": "外部事件管理系统", "xpack.cases.caseView.copyCommentLinkAria": "复制引用链接", "xpack.cases.caseView.create": "创建案例", diff --git a/x-pack/test/functional/page_objects/observability_page.ts b/x-pack/test/functional/page_objects/observability_page.ts index 0177939ec3d15..bfbd1741d9f11 100644 --- a/x-pack/test/functional/page_objects/observability_page.ts +++ b/x-pack/test/functional/page_objects/observability_page.ts @@ -11,6 +11,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function ObservabilityPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); + const textValue = 'Foobar'; return { async clickSolutionNavigationEntry(appId: string, navId: string) { @@ -44,6 +45,7 @@ export function ObservabilityPageProvider({ getService, getPageObjects }: FtrPro }, async expectAddCommentButton() { + await testSubjects.setValue('add-comment', textValue); const button = await testSubjects.find('submit-comment', 20000); const disabledAttr = await button.getAttribute('disabled'); expect(disabledAttr).to.be(null); From 7261175571b0bcfd68c538067c60eac12dad84e1 Mon Sep 17 00:00:00 2001 From: Khristinin Nikita Date: Mon, 5 Dec 2022 19:01:02 +0100 Subject: [PATCH 23/40] Remove id from item list (#146805) ## Remove id from item list when try to close alerts during update exceptions close: https://github.com/elastic/kibana/issues/146661 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../rule_exceptions/utils/helpers.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx index 41d588a23763a..b1ee787ef60cd 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type { EuiCommentProps } from '@elastic/eui'; import { EuiText, EuiAvatar } from '@elastic/eui'; -import { capitalize } from 'lodash'; +import { capitalize, omit } from 'lodash'; import moment from 'moment'; import type { @@ -143,11 +143,12 @@ export const prepareExceptionItemsForBulkClose = ( return exceptionItems.map((item: ExceptionListItemSchema) => { if (item.entries !== undefined) { const newEntries = item.entries.map((itemEntry: Entry | EntryNested) => { + const entry = omit(itemEntry, 'id') as Entry | EntryNested; return { - ...itemEntry, - field: itemEntry.field.startsWith('event.') - ? itemEntry.field.replace(/^event./, `${ALERT_ORIGINAL_EVENT}.`) - : itemEntry.field, + ...entry, + field: entry.field.startsWith('event.') + ? entry.field.replace(/^event./, `${ALERT_ORIGINAL_EVENT}.`) + : entry.field, }; }); return { From b12859fed924e5327d4c936166d3c4b475984507 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 5 Dec 2022 13:32:16 -0500 Subject: [PATCH 24/40] [Fleet] Honor source_mode defined in a package datastream when installing it (#147019) --- .../elasticsearch/template/install.test.ts | 34 +++++++++++++++++++ .../epm/elasticsearch/template/install.ts | 12 ++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts index 3478da69bf721..d8cc0e93c9ea0 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts @@ -88,4 +88,38 @@ describe('EPM index template install', () => { expect(indexTemplate.priority).toBe(templatePriorityDatasetIsPrefixTrue); expect(indexTemplate.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixTrue]); }); + + it('tests prepareTemplate to set source mode to synthetics if specified', async () => { + const dataStreamDatasetIsPrefixTrue = { + type: 'metrics', + dataset: 'package.dataset', + title: 'test data stream', + release: 'experimental', + package: 'package', + path: 'path', + ingest_pipeline: 'default', + dataset_is_prefix: true, + elasticsearch: { + source_mode: 'synthetic', + }, + } as RegistryDataStream; + const pkg = { + name: 'package', + version: '0.0.1', + }; + + const { componentTemplates } = prepareTemplate({ + pkg, + dataStream: dataStreamDatasetIsPrefixTrue, + }); + + const packageTemplate = componentTemplates['metrics-package.dataset@package'].template; + + if (!('mappings' in packageTemplate)) { + throw new Error('no mappings on package template'); + } + + expect(packageTemplate.mappings).toHaveProperty('_source'); + expect(packageTemplate.mappings._source).toEqual({ mode: 'synthetic' }); + }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index ca03d272405f4..5d30433e80d4b 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -290,7 +290,17 @@ export function buildComponentTemplates(params: { mappings: { properties: mappingsProperties, dynamic_templates: mappingsDynamicTemplates.length ? mappingsDynamicTemplates : undefined, - ...omit(indexTemplateMappings, 'properties', 'dynamic_templates'), + ...omit(indexTemplateMappings, 'properties', 'dynamic_templates', '_source'), + ...(indexTemplateMappings?._source || registryElasticsearch?.source_mode + ? { + _source: { + ...indexTemplateMappings?._source, + ...(registryElasticsearch?.source_mode === 'synthetic' + ? { mode: 'synthetic' } + : {}), + }, + } + : {}), }, }, _meta, From 7e9f57ccce7a01883251928297411b9b579f97ab Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Mon, 5 Dec 2022 13:51:08 -0500 Subject: [PATCH 25/40] [Uptime] monitor management - adjust deletion logic (#146908) ## Summary Resolves https://github.com/elastic/kibana/issues/146932 Adjusts monitor delete logic for Uptime to ensure that multiple monitors are able to be deleted in a row. ### Testing 1. Create at least two monitors 2. Navigate to Uptime monitor management. Delete a monitor. Ensure the success toast appears and the monitor is removed from the monitor list 3. Delete a second monitor. Ensure the success toast appears and the monitor is removed from the list. Co-authored-by: shahzad31 --- .../monitor_list/actions.tsx | 1 + .../monitor_list/delete_monitor.test.tsx | 70 +++++------ .../monitor_list/delete_monitor.tsx | 111 +++++------------- .../monitor_list/monitor_list.tsx | 2 +- .../lib/__mocks__/uptime_store.mock.ts | 1 + .../lib/helper/helper_with_redux.tsx | 16 +-- .../legacy_uptime/lib/helper/rtl_helpers.tsx | 14 ++- .../state/actions/delete_monitor.ts | 14 +++ .../legacy_uptime/state/actions/types.ts | 8 +- .../legacy_uptime/state/actions/utils.ts | 10 +- .../state/effects/delete_monitor.tsx | 52 ++++++++ .../legacy_uptime/state/effects/index.ts | 2 + .../state/reducers/delete_monitor.ts | 56 +++++++++ .../legacy_uptime/state/reducers/index.ts | 3 + .../legacy_uptime/state/selectors/index.ts | 9 ++ .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 18 files changed, 230 insertions(+), 142 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/legacy_uptime/state/actions/delete_monitor.ts create mode 100644 x-pack/plugins/synthetics/public/legacy_uptime/state/effects/delete_monitor.tsx create mode 100644 x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/delete_monitor.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/actions.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/actions.tsx index 78e46f6a0fea8..9442920eee1f6 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/actions.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/actions.tsx @@ -75,6 +75,7 @@ export const Actions = ({ ', () => { const onUpdate = jest.fn(); - const useFetcher = spyOnUseFetcher({}); - it('calls delete monitor on monitor deletion', () => { - useFetcher.mockImplementation(originalUseFetcher); + it('calls delete monitor on monitor deletion', async () => { const deleteMonitor = jest.spyOn(fetchers, 'deleteMonitor'); const id = 'test-id'; - render(); + const store = createRealStore(); + render(, { + store, + }); + + const dispatchSpy = jest.spyOn(store, 'dispatch'); expect(deleteMonitor).not.toBeCalled(); @@ -37,12 +39,24 @@ describe('', () => { fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); - expect(deleteMonitor).toBeCalledWith({ id }); + expect(dispatchSpy).toHaveBeenCalledWith({ + payload: { + id: 'test-id', + name: 'sample name', + }, + type: 'DELETE_MONITOR', + }); + + expect(store.getState().deleteMonitor.loading.includes(id)).toEqual(true); + + expect(await screen.findByLabelText('Loading')).toBeTruthy(); }); - it('calls set refresh when deletion is successful', () => { + it('calls set refresh when deletion is successful', async () => { const id = 'test-id'; const name = 'sample monitor'; + const store = createRealStore(); + render( ', () => { }, ] as unknown as MonitorManagementListResult['monitors'] } - /> + />, + { store } ); - userEvent.click(screen.getByTestId('monitorManagementDeleteMonitor')); + fireEvent.click(screen.getByRole('button')); - expect(onUpdate).toHaveBeenCalled(); - }); + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); - it('shows loading spinner while waiting for monitor to delete', () => { - const id = 'test-id'; - useFetcher.mockReturnValue({ - data: {}, - status: FETCH_STATUS.LOADING, - refetch: () => {}, + await waitFor(() => { + expect(onUpdate).toHaveBeenCalled(); }); - render( - - ); - expect(screen.getByLabelText('Deleting monitor...')).toBeInTheDocument(); + expect(store.getState().deleteMonitor.deletedMonitorIds.includes(id)).toEqual(true); }); }); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/delete_monitor.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/delete_monitor.tsx index ebec71c14c477..d82613d7a2ab0 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/delete_monitor.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/delete_monitor.tsx @@ -7,22 +7,19 @@ import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; -import { - EuiButtonIcon, - EuiCallOut, - EuiConfirmModal, - EuiLoadingSpinner, - EuiSpacer, -} from '@elastic/eui'; - -import { FETCH_STATUS, useFetcher } from '@kbn/observability-plugin/public'; -import { toMountPoint } from '@kbn/kibana-react-plugin/public'; +import { EuiButtonIcon, EuiCallOut, EuiConfirmModal, EuiSpacer } from '@elastic/eui'; + +import { useDispatch, useSelector } from 'react-redux'; +import { deleteMonitorAction } from '../../../state/actions/delete_monitor'; +import { AppState } from '../../../state'; import { ProjectMonitorDisclaimer, PROJECT_MONITOR_TITLE, } from '../../../../apps/synthetics/components/monitors_page/management/monitor_list_table/delete_monitor'; -import { deleteMonitor } from '../../../state/api'; -import { kibanaService } from '../../../state/kibana_service'; +import { + deleteMonitorLoadingSelector, + deleteMonitorSuccessSelector, +} from '../../../state/selectors'; export const DeleteMonitor = ({ configId, @@ -37,61 +34,34 @@ export const DeleteMonitor = ({ isProjectMonitor?: boolean; onUpdate: () => void; }) => { - const [isDeleting, setIsDeleting] = useState(false); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); + const isDeleting = useSelector((state: AppState) => + deleteMonitorLoadingSelector(state, configId) + ); + + const isSuccessfullyDeleted = useSelector((state: AppState) => + deleteMonitorSuccessSelector(state, configId) + ); + + const dispatch = useDispatch(); + const onConfirmDelete = () => { - setIsDeleting(true); + dispatch(deleteMonitorAction.get({ id: configId, name })); setIsDeleteModalVisible(false); }; - const showDeleteModal = () => setIsDeleteModalVisible(true); - const { status } = useFetcher(() => { - if (isDeleting) { - return deleteMonitor({ id: configId }); - } - }, [configId, isDeleting]); + const showDeleteModal = () => setIsDeleteModalVisible(true); const handleDelete = () => { showDeleteModal(); }; useEffect(() => { - if (!isDeleting) { - return; - } - if (status === FETCH_STATUS.SUCCESS || status === FETCH_STATUS.FAILURE) { - setIsDeleting(false); - } - if (status === FETCH_STATUS.FAILURE) { - kibanaService.toasts.addDanger( - { - title: toMountPoint( -

{MONITOR_DELETE_FAILURE_LABEL}

- ), - }, - { toastLifeTimeMs: 3000 } - ); - } else if (status === FETCH_STATUS.SUCCESS) { + if (isSuccessfullyDeleted) { onUpdate(); - kibanaService.toasts.addSuccess( - { - title: toMountPoint( -

- {i18n.translate( - 'xpack.synthetics.monitorManagement.monitorDeleteSuccessMessage.name', - { - defaultMessage: 'Deleted "{name}"', - values: { name }, - } - )} -

- ), - }, - { toastLifeTimeMs: 3000 } - ); } - }, [setIsDeleting, onUpdate, status, name, isDeleting]); + }, [onUpdate, isSuccessfullyDeleted]); const destroyModal = ( - {status === FETCH_STATUS.LOADING ? ( - - ) : ( - - )} + + {isDeleteModalVisible && destroyModal} ); @@ -151,18 +119,3 @@ const DELETE_MONITOR_LABEL = i18n.translate( defaultMessage: 'Delete monitor', } ); - -// TODO: Discuss error states with product -const MONITOR_DELETE_FAILURE_LABEL = i18n.translate( - 'xpack.synthetics.monitorManagement.monitorDeleteFailureMessage', - { - defaultMessage: 'Monitor was unable to be deleted. Please try again later.', - } -); - -const MONITOR_DELETE_LOADING_LABEL = i18n.translate( - 'xpack.synthetics.monitorManagement.monitorDeleteLoadingMessage', - { - defaultMessage: 'Deleting monitor...', - } -); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx index 7e475a0c7116a..93fea9ca0acc3 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx @@ -180,7 +180,6 @@ export const MonitorManagementList = ({ }), sortable: true, render: (urls: string, { hosts }: TCPSimpleFields | ICMPSimpleFields) => urls || hosts, - truncateText: true, textOnly: true, }, { @@ -205,6 +204,7 @@ export const MonitorManagementList = ({ }), render: (fields: EncryptedSyntheticsMonitorWithId) => ( { +export const createRealStore = (): Store => { const sagaMW = createSagaMiddleware(); const store = createReduxStore(rootReducer, applyMiddleware(sagaMW)); sagaMW.run(rootEffect); return store; }; -export const MountWithReduxProvider: React.FC<{ state?: AppState; useRealStore?: boolean }> = ({ - children, - state, - useRealStore, -}) => { - const store = useRealStore +export const MountWithReduxProvider: React.FC<{ + state?: AppState; + useRealStore?: boolean; + store?: Store; +}> = ({ children, state, store, useRealStore }) => { + const newStore = useRealStore ? createRealStore() : { dispatch: jest.fn(), @@ -38,5 +38,5 @@ export const MountWithReduxProvider: React.FC<{ state?: AppState; useRealStore?: [Symbol.observable]: jest.fn(), }; - return {children}; + return {children}; }; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx index 4435ab081192b..e1bee1d621f12 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx @@ -28,6 +28,7 @@ import { KibanaContextProvider, KibanaServices } from '@kbn/kibana-react-plugin/ import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; +import { Store } from 'redux'; import { mockState } from '../__mocks__/uptime_store.mock'; import { MountWithReduxProvider } from './helper_with_redux'; import { AppState } from '../../state'; @@ -221,12 +222,17 @@ export function WrappedHelper({ url, useRealStore, path, + store, history = createMemoryHistory(), -}: RenderRouterOptions & { children: ReactElement; useRealStore?: boolean }) { +}: RenderRouterOptions & { + children: ReactElement; + useRealStore?: boolean; + store?: Store; +}) { const testState: AppState = merge({}, mockState, state); return ( - + {children} @@ -246,7 +252,8 @@ export function render( url, path, useRealStore, - }: RenderRouterOptions & { useRealStore?: boolean } = {} + store, + }: RenderRouterOptions & { useRealStore?: boolean; store?: Store } = {} ): any { if (url) { history = getHistoryFromUrl(url); @@ -262,6 +269,7 @@ export function render( state={state} path={path} useRealStore={useRealStore} + store={store} > {ui} , diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/delete_monitor.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/delete_monitor.ts new file mode 100644 index 0000000000000..194b02cd16038 --- /dev/null +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/delete_monitor.ts @@ -0,0 +1,14 @@ +/* + * 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 { createAsyncAction } from './utils'; + +export const deleteMonitorAction = createAsyncAction< + { id: string; name: string }, + string, + { id: string; error: Error } +>('DELETE_MONITOR'); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/types.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/types.ts index 5ddc90be61f23..739cadb2d65b9 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/types.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/types.ts @@ -10,13 +10,13 @@ import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { Rule } from '@kbn/triggers-actions-ui-plugin/public'; import type { UptimeAlertTypeParams } from '../alerts/alerts'; -export interface AsyncAction { +export interface AsyncAction { get: (payload: Payload) => Action; success: (payload: SuccessPayload) => Action; - fail: (payload: IHttpFetchError) => Action; + fail: (payload: ErrorPayload) => Action; } -export interface AsyncActionOptionalPayload - extends AsyncAction { +export interface AsyncActionOptionalPayload + extends AsyncAction { get: (payload?: Payload) => Action; } diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/utils.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/utils.ts index 6e8f15ec3780f..cd930061459f8 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/utils.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/actions/utils.ts @@ -9,15 +9,15 @@ import { createAction } from 'redux-actions'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { AsyncAction, AsyncActionOptionalPayload } from './types'; -export function createAsyncAction( +export function createAsyncAction( actionStr: string -): AsyncActionOptionalPayload; -export function createAsyncAction( +): AsyncActionOptionalPayload; +export function createAsyncAction( actionStr: string -): AsyncAction { +): AsyncAction { return { get: createAction(actionStr), success: createAction(`${actionStr}_SUCCESS`), - fail: createAction(`${actionStr}_FAIL`), + fail: createAction(`${actionStr}_FAIL`), }; } diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/delete_monitor.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/delete_monitor.tsx new file mode 100644 index 0000000000000..fc4a68c974620 --- /dev/null +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/delete_monitor.tsx @@ -0,0 +1,52 @@ +/* + * 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 React from 'react'; +import { toMountPoint } from '@kbn/kibana-react-plugin/public'; +import { put, call, takeEvery } from 'redux-saga/effects'; +import { Action } from 'redux-actions'; +import { i18n } from '@kbn/i18n'; +import { deleteMonitorAction } from '../actions/delete_monitor'; +import { deleteMonitor } from '../api'; +import { kibanaService } from '../kibana_service'; + +export function* deleteMonitorEffect() { + yield takeEvery( + String(deleteMonitorAction.get), + function* (action: Action<{ id: string; name: string }>) { + try { + const { id, name } = action.payload; + yield call(deleteMonitor, { id }); + yield put(deleteMonitorAction.success(id)); + kibanaService.core.notifications.toasts.addSuccess({ + title: toMountPoint( +

+ {i18n.translate( + 'xpack.synthetics.monitorManagement.monitorDeleteSuccessMessage.name', + { + defaultMessage: 'Deleted "{name}"', + values: { name }, + } + )} +

+ ), + }); + } catch (err) { + kibanaService.core.notifications.toasts.addError(err, { + title: MONITOR_DELETE_FAILURE_LABEL, + }); + yield put(deleteMonitorAction.fail({ id: action.payload.id, error: err })); + } + } + ); +} + +const MONITOR_DELETE_FAILURE_LABEL = i18n.translate( + 'xpack.synthetics.monitorManagement.monitorDeleteFailureMessage', + { + defaultMessage: 'Monitor was unable to be deleted. Please try again later.', + } +); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/index.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/index.ts index 07df2a909d4b8..3fade3e59257e 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/index.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/effects/index.ts @@ -6,6 +6,7 @@ */ import { fork } from 'redux-saga/effects'; +import { deleteMonitorEffect } from './delete_monitor'; import { fetchAgentPoliciesEffect } from '../private_locations'; import { fetchMonitorDetailsEffect } from './monitor'; import { fetchMonitorListEffect, fetchUpdatedMonitorEffect } from './monitor_list'; @@ -51,4 +52,5 @@ export function* rootEffect() { yield fork(pruneBlockCache); yield fork(fetchSyntheticsServiceAllowedEffect); yield fork(fetchAgentPoliciesEffect); + yield fork(deleteMonitorEffect); } diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/delete_monitor.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/delete_monitor.ts new file mode 100644 index 0000000000000..b28cc214f0e8b --- /dev/null +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/delete_monitor.ts @@ -0,0 +1,56 @@ +/* + * 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 { createReducer, PayloadAction } from '@reduxjs/toolkit'; +import { WritableDraft } from 'immer/dist/types/types-external'; +import { deleteMonitorAction } from '../actions/delete_monitor'; + +export interface DeleteMonitorState { + error?: Record; + loading?: string[]; + deletedMonitorIds?: string[]; +} + +export const initialState: DeleteMonitorState = { + error: {}, + loading: [], + deletedMonitorIds: [], +}; + +export const deleteMonitorReducer = createReducer(initialState, (builder) => { + builder + .addCase( + String(deleteMonitorAction.get), + ( + state: WritableDraft, + action: PayloadAction<{ id: string; name: string }> + ) => ({ + ...state, + loading: [...(state.loading ?? []), action.payload.id], + error: { ...state.error, [action.payload.id]: undefined }, + }) + ) + .addCase( + String(deleteMonitorAction.success), + (state: WritableDraft, action: PayloadAction) => ({ + ...state, + loading: state.loading?.filter((id) => id !== action.payload), + deletedMonitorIds: [...(state.deletedMonitorIds ?? []), action.payload], + }) + ) + .addCase( + String(deleteMonitorAction.fail), + ( + state: WritableDraft, + action: PayloadAction<{ id: string; error: Error }> + ) => ({ + ...state, + loading: state.loading?.filter((id) => id !== action.payload.id), + error: { ...state.error, [action.payload.id]: action.payload.error }, + }) + ); +}); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/index.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/index.ts index dc4db2d58ac61..554d8f1a44cd8 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/index.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/reducers/index.ts @@ -6,6 +6,7 @@ */ import { combineReducers } from 'redux'; +import { deleteMonitorReducer, DeleteMonitorState } from './delete_monitor'; import { agentPoliciesReducer, AgentPoliciesState } from '../private_locations'; import { monitorReducer, MonitorState } from './monitor'; import { uiReducer, UiState } from './ui'; @@ -47,6 +48,7 @@ export interface RootState { synthetics: SyntheticsReducerState; testNowRuns: TestNowRunsState; agentPolicies: AgentPoliciesState; + deleteMonitor: DeleteMonitorState; } export const rootReducer = combineReducers({ @@ -69,4 +71,5 @@ export const rootReducer = combineReducers({ synthetics: syntheticsReducer, testNowRuns: testNowRunsReducer, agentPolicies: agentPoliciesReducer, + deleteMonitor: deleteMonitorReducer, }); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/selectors/index.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/selectors/index.ts index d250eb8bcf059..8a91c017635ae 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/selectors/index.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/selectors/index.ts @@ -19,6 +19,15 @@ export const monitorDetailsSelector = (state: AppState, summary: any) => { return state.monitor.monitorDetailsList[summary.monitor_id]; }; +export const deleteMonitorLoadingSelector = (state: AppState, id?: string) => { + if (!id) return (state.deleteMonitor.loading ?? []).length > 0; + return state.deleteMonitor.loading?.includes(id) ?? false; +}; + +export const deleteMonitorSuccessSelector = (state: AppState, id: string) => { + return state.deleteMonitor.deletedMonitorIds?.includes(id) ?? false; +}; + export const monitorDetailsLoadingSelector = (state: AppState) => state.monitor.loading; export const monitorLocationsSelector = (state: AppState, monitorId: string) => { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index b2746c0c2fd82..275268ecc2883 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31082,7 +31082,6 @@ "xpack.synthetics.monitorManagement.monitorAdvancedOptions.monitorNamespaceFieldLabel": "Espace de nom", "xpack.synthetics.monitorManagement.monitorAdvancedOptions.namespaceHelpLearnMoreLabel": "En savoir plus", "xpack.synthetics.monitorManagement.monitorDeleteFailureMessage": "Impossible de supprimer le moniteur. Réessayez plus tard.", - "xpack.synthetics.monitorManagement.monitorDeleteLoadingMessage": "Suppression du moniteur...", "xpack.synthetics.monitorManagement.monitorEditedSuccessMessage": "Moniteur mis à jour.", "xpack.synthetics.monitorManagement.monitorFailureMessage": "Impossible d'enregistrer le moniteur. Réessayez plus tard.", "xpack.synthetics.monitorManagement.monitorList.actions": "Actions", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 245b2a33195fe..58bd193a4ba78 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31058,7 +31058,6 @@ "xpack.synthetics.monitorManagement.monitorAdvancedOptions.monitorNamespaceFieldLabel": "名前空間", "xpack.synthetics.monitorManagement.monitorAdvancedOptions.namespaceHelpLearnMoreLabel": "詳細情報", "xpack.synthetics.monitorManagement.monitorDeleteFailureMessage": "モニターを削除できませんでした。しばらくたってから再試行してください。", - "xpack.synthetics.monitorManagement.monitorDeleteLoadingMessage": "モニターを削除しています...", "xpack.synthetics.monitorManagement.monitorEditedSuccessMessage": "モニターは正常に更新されました。", "xpack.synthetics.monitorManagement.monitorFailureMessage": "モニターを保存できませんでした。しばらくたってから再試行してください。", "xpack.synthetics.monitorManagement.monitorList.actions": "アクション", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 87b560ac76f5c..edb5ad718e653 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -31093,7 +31093,6 @@ "xpack.synthetics.monitorManagement.monitorAdvancedOptions.monitorNamespaceFieldLabel": "命名空间", "xpack.synthetics.monitorManagement.monitorAdvancedOptions.namespaceHelpLearnMoreLabel": "了解详情", "xpack.synthetics.monitorManagement.monitorDeleteFailureMessage": "无法删除监测。请稍后重试。", - "xpack.synthetics.monitorManagement.monitorDeleteLoadingMessage": "正在删除监测......", "xpack.synthetics.monitorManagement.monitorEditedSuccessMessage": "已成功更新监测。", "xpack.synthetics.monitorManagement.monitorFailureMessage": "无法保存监测。请稍后重试。", "xpack.synthetics.monitorManagement.monitorList.actions": "操作", From a433b647e4b86b116d464b27696ca434ddcee967 Mon Sep 17 00:00:00 2001 From: Bhavya RM Date: Mon, 5 Dec 2022 14:55:34 -0500 Subject: [PATCH 26/40] Fixing upgrade dashboard smoke test render error (#147037) --- x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts index 341d4af0e4c64..105620f90d6b7 100644 --- a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts @@ -51,6 +51,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should render visualizations', async () => { await PageObjects.home.launchSampleDashboard('flights'); await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.timePicker.setCommonlyUsedTime('Last_1 year'); await renderable.waitForRender(); log.debug('Checking saved searches rendered'); await dashboardExpect.savedSearchRowCount(49); From b6696ef6c7da83c0ef396d24f471cb6589e5413a Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Mon, 5 Dec 2022 15:13:19 -0500 Subject: [PATCH 27/40] [Fleet] Ensure top-level package vars are parsed when reading archive (#147040) ## Summary Closes https://github.com/elastic/kibana/issues/147028 ## Testing instructions See steps to reproduce in linked issue. Verify AWS credential variables appear on this branch. ![image](https://user-images.githubusercontent.com/6766512/205719634-98bc4db8-25c4-4362-afba-5246fb5fb326.png) I took a pass at adding tests for our `parseAndVeryArchive` method but it's sort of a recursive chain of mocked `Buffer` -> `yaml.safeLoad` operations and got pretty involved to set up from scratch. The other option would be to add an FTR API test that catches this case, but we'd need a package with top-level variables loaded into the test registry, which we may not have readily available if https://github.com/elastic/kibana/pull/146809 lands. I would love some alternative ideas on adding test coverage for this fix, but if it's going to involved I don't want to block this fix from landing in 8.6 on tests. --- x-pack/plugins/fleet/server/services/epm/archive/parse.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/fleet/server/services/epm/archive/parse.ts b/x-pack/plugins/fleet/server/services/epm/archive/parse.ts index 9ef677b796ce8..80642496c4fb8 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/parse.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/parse.ts @@ -252,6 +252,11 @@ function parseAndVerifyArchive( semverPrerelease(parsed.version) || semverMajor(parsed.version) < 1 ? 'beta' : 'ga'; } + // Ensure top-level variables are parsed as well + if (manifest.vars) { + parsed.vars = parseAndVerifyVars(manifest.vars, 'manifest.yml'); + } + return parsed; } From 81635fca7300ca81b9fc87c2c3a754e7851a5c30 Mon Sep 17 00:00:00 2001 From: Wafaa Nasr Date: Mon, 5 Dec 2022 22:02:05 +0100 Subject: [PATCH 28/40] [Security Solution]: List details page fix Linked Rules max height (#147039) ## Summary - Applying a max-height to the `Linked Rules` combobox in the List Shared details as well as in the Add Exception Items --- .../header_menu/__snapshots__/header_menu.test.tsx.snap | 2 +- .../src/header_menu/index.tsx | 9 +++++++++ .../list_header/__snapshots__/list_header.test.tsx.snap | 2 +- .../menu_items/__snapshots__/menu_items.test.tsx.snap | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap b/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap index c8a87dd515a73..412add3e45c26 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap +++ b/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap @@ -176,7 +176,7 @@ Object {

diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx index d6789386819d6..f042be34a8cee 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx +++ b/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx @@ -20,6 +20,7 @@ import { } from '@elastic/eui'; import { ButtonContentIconSide } from '@elastic/eui/src/components/button/_button_content_deprecated'; +import { css } from '@emotion/react'; export interface Action { key: string; @@ -42,6 +43,12 @@ interface HeaderMenuComponentProps { panelPaddingSize?: PanelPaddingSize; } +const popoverHeightStyle = css` + max-height: 300px; + height: 100%; + overflow-x: hidden; + overflow-y: auto; +`; const HeaderMenuComponent: FC = ({ text, dataTestSubj, @@ -114,6 +121,8 @@ const HeaderMenuComponent: FC = ({ > {!itemActions ? null : (
diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap b/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap index 24f086b897db4..092ac9271ea57 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap +++ b/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap @@ -499,7 +499,7 @@ Object {

@@ -779,7 +779,7 @@ Object {

From 83a334974c9d15ab3b45a5130979dcf5f6212382 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Mon, 5 Dec 2022 17:06:36 -0500 Subject: [PATCH 29/40] [Security Solution] [Exceptions] Only use z-index 5000 when exceptions within timeline (#147024) ## Summary This pr is a bit of a hack to get around an issue with eui portals and the z-index of the timeline, as the tags super select that is displayed when the exceptions flyout is opened when not specifically for a rule instance, renders below the flyout due to z-index of 5000. This change makes it so that the flyout has a z-index of 1000 in that case, and 5000 in the timeline view, so that all elements are visible as expected. https://user-images.githubusercontent.com/56408403/205704409-9379e5af-2f01-45f0-b5d9-8479ac892b65.mov --- .../rule_exceptions/components/add_exception_flyout/index.tsx | 4 +++- .../public/exceptions/pages/shared_lists/index.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx index f6e3513c59c07..9366dbd04a9e7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx @@ -77,6 +77,7 @@ export interface AddExceptionFlyoutProps { sharedListToAddTo?: ExceptionListSchema[]; onCancel: (didRuleChange: boolean) => void; onConfirm: (didRuleChange: boolean, didCloseAlert: boolean, didBulkCloseAlert: boolean) => void; + isNonTimeline?: boolean; } const FlyoutBodySection = styled(EuiFlyoutBody)` @@ -110,6 +111,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ sharedListToAddTo, onCancel, onConfirm, + isNonTimeline = false, }: AddExceptionFlyoutProps) { const { isLoading, indexPatterns } = useFetchIndexPatterns(rules); const [isSubmitting, submitNewExceptionItems] = useAddNewExceptionItems(); @@ -425,7 +427,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ return ( { showAlertCloseOptions onCancel={(didRuleChange: boolean) => setDisplayAddExceptionItemFlyout(false)} onConfirm={(didRuleChange: boolean) => setDisplayAddExceptionItemFlyout(false)} + isNonTimeline={true} /> )} From b79954c9b7e4b17f87c0a07ace5d95ae3ef3d4b1 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 5 Dec 2022 17:44:13 -0500 Subject: [PATCH 30/40] [Security Solution] Fix Endpoint tests when prepackaged with a dev endpoint package (#147052) ## Summary Change our query to use `prerelease` to correctly find dev endpoint packages in tests ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- fleet_packages.json | 2 +- .../test/security_solution_endpoint/services/endpoint_policy.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fleet_packages.json b/fleet_packages.json index 78df6752f3a8a..10f7e5d8b0994 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -29,7 +29,7 @@ }, { "name": "endpoint", - "version": "8.6.1" + "version": "8.7.0-next" }, { "name": "fleet_server", diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts index 9d90e2530c18c..db2f12694ac7c 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts @@ -33,7 +33,7 @@ const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`; const INGEST_API_PACKAGE_POLICIES_DELETE = `${INGEST_API_PACKAGE_POLICIES}/delete`; const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`; -const SECURITY_PACKAGES_ROUTE = `${INGEST_API_EPM_PACKAGES}?category=security&experimental=true`; +const SECURITY_PACKAGES_ROUTE = `${INGEST_API_EPM_PACKAGES}?category=security&prerelease=true`; /** * Holds information about the test resources created to support an Endpoint Policy From 4bf488b620e8fe2111d74b70c4bd6a6cb4dfd80b Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Mon, 5 Dec 2022 22:36:57 -0600 Subject: [PATCH 31/40] [data view editor] State service cleanup (#146944) ## Summary - Single observable for internal state - Selector style creation of observables for individual usage in react code - internal `stateUpdate` fn that sets internal state and emits new observable value --- .../public/data_view_editor_service.ts | 97 ++++++++++++------- 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/src/plugins/data_view_editor/public/data_view_editor_service.ts b/src/plugins/data_view_editor/public/data_view_editor_service.ts index 3589f7d491904..4bfd04c912a6c 100644 --- a/src/plugins/data_view_editor/public/data_view_editor_service.ts +++ b/src/plugins/data_view_editor/public/data_view_editor_service.ts @@ -15,6 +15,8 @@ import { from, Observable, Subscription, + map, + distinctUntilChanged, } from 'rxjs'; import { @@ -48,6 +50,29 @@ export interface DataViewEditorServiceConstructorArgs { }; } +interface DataViewEditorState { + matchedIndices: MatchedIndicesSet; + rollupIndicesCaps: RollupIndicesCapsResponse; + isLoadingSourcesInternal: boolean; + loadingTimestampFields: boolean; + timestampFieldOptions: TimestampOption[]; + rollupIndexName?: string | null; +} + +const defaultDataViewEditorState: DataViewEditorState = { + matchedIndices: { ...matchedIndiciesDefault }, + rollupIndicesCaps: {}, + isLoadingSourcesInternal: false, + loadingTimestampFields: false, + timestampFieldOptions: [], + rollupIndexName: undefined, +}; + +export const stateSelectorFactory = + (state$: Observable) => + (selector: (state: S) => R, equalityFn?: (arg0: R, arg1: R) => boolean) => + state$.pipe(map(selector), distinctUntilChanged(equalityFn)); + export class DataViewEditorService { constructor({ services: { http, dataViews }, @@ -68,13 +93,19 @@ export class DataViewEditorService { this.rollupCapsResponse = this.getRollupIndexCaps(); this.dataViewNames$ = from(this.loadDataViewNames(initialName)); + this.state$ = new BehaviorSubject({ + ...defaultDataViewEditorState, + }); + + const stateSelector = stateSelectorFactory(this.state$); + // public observables - this.matchedIndices$ = this.matchedIndicesInternal$.asObservable(); - this.rollupIndicesCaps$ = this.rollupIndicesCapsInternal$.asObservable(); - this.isLoadingSources$ = this.isLoadingSourcesInternal$.asObservable(); - this.loadingTimestampFields$ = this.loadingTimestampFieldsInternal$.asObservable(); - this.timestampFieldOptions$ = this.timestampFieldOptionsInternal$.asObservable(); - this.rollupIndex$ = this.rollupIndexInternal$.asObservable(); + this.matchedIndices$ = stateSelector((state) => state.matchedIndices); + this.rollupIndicesCaps$ = stateSelector((state) => state.rollupIndicesCaps); + this.isLoadingSources$ = stateSelector((state) => state.isLoadingSourcesInternal); + this.loadingTimestampFields$ = stateSelector((state) => state.loadingTimestampFields); + this.timestampFieldOptions$ = stateSelector((state) => state.timestampFieldOptions); + this.rollupIndex$ = stateSelector((state) => state.rollupIndexName); // when list of matched indices is updated always update timestamp fields this.loadTimestampFieldsSub = this.matchedIndices$.subscribe(() => this.loadTimestampFields()); @@ -99,6 +130,7 @@ export class DataViewEditorService { private type = INDEX_PATTERN_TYPE.DEFAULT; // state + private state = { ...defaultDataViewEditorState }; private indexPattern = ''; private allowHidden = false; @@ -109,24 +141,19 @@ export class DataViewEditorService { private matchedIndicesForProviderSub: Subscription; private rollupIndexForProviderSub: Subscription; + private state$: BehaviorSubject; + // used for validating rollup data views - must match one and only one data view - private rollupIndicesCapsInternal$ = new BehaviorSubject({}); rollupIndicesCaps$: Observable; - private isLoadingSourcesInternal$ = new BehaviorSubject(false); isLoadingSources$: Observable; - - private loadingTimestampFieldsInternal$ = new BehaviorSubject(false); loadingTimestampFields$: Observable; - private timestampFieldOptionsInternal$ = new Subject(); timestampFieldOptions$: Observable; // current matched rollup index - private rollupIndexInternal$ = new BehaviorSubject(undefined); rollupIndex$: Observable; // alernates between value and undefined so validation can treat new value as thought its a promise private rollupIndexForProvider$ = new Subject(); - private matchedIndicesInternal$ = new BehaviorSubject(matchedIndiciesDefault); matchedIndices$: Observable; // alernates between value and undefined so validation can treat new value as thought its a promise @@ -137,15 +164,20 @@ export class DataViewEditorService { private currentLoadingTimestampFields = 0; private currentLoadingMatchedIndices = 0; + private updateState = (newState: Partial) => { + this.state = { ...this.state, ...newState }; + this.state$.next(this.state); + }; + private getRollupIndexCaps = async () => { - let response: RollupIndicesCapsResponse = {}; + let rollupIndicesCaps: RollupIndicesCapsResponse = {}; try { - response = await this.http.get('/api/rollup/indices'); + rollupIndicesCaps = await this.http.get('/api/rollup/indices'); } catch (e) { // Silently swallow failure responses such as expired trials } - this.rollupIndicesCapsInternal$.next(response); - return response; + this.updateState({ rollupIndicesCaps }); + return rollupIndicesCaps; }; private getIsRollupIndex = async () => { @@ -165,7 +197,7 @@ export class DataViewEditorService { const indexRequests = []; let newRollupIndexName: string | undefined | null; - this.loadingTimestampFieldsInternal$.next(true); + this.updateState({ loadingTimestampFields: true }); if (query?.endsWith('*')) { const exactMatchedQuery = this.getIndicesCached({ @@ -194,24 +226,19 @@ export class DataViewEditorService { indexRequests )) as MatchedItem[][]; - const matchedIndicesResult = getMatchedIndices( - allSources, - partialMatched, - exactMatched, - allowHidden - ); + const matchedIndices = getMatchedIndices(allSources, partialMatched, exactMatched, allowHidden); // verify we're looking at the current result if (currentLoadingMatchedIndicesIdx === this.currentLoadingMatchedIndices) { if (type === INDEX_PATTERN_TYPE.ROLLUP) { const rollupIndices = exactMatched.filter((index) => isRollupIndex(index.name)); newRollupIndexName = rollupIndices.length === 1 ? rollupIndices[0].name : null; - this.rollupIndexInternal$.next(newRollupIndexName); + this.updateState({ rollupIndexName: newRollupIndexName }); } else { - this.rollupIndexInternal$.next(null); + this.updateState({ rollupIndexName: null }); } - this.matchedIndicesInternal$.next(matchedIndicesResult); + this.updateState({ matchedIndices }); } }; @@ -237,7 +264,7 @@ export class DataViewEditorService { }); await this.loadMatchedIndices(this.indexPattern, this.allowHidden, allSrcs, this.type); - this.isLoadingSourcesInternal$.next(false); + this.updateState({ isLoadingSourcesInternal: false }); }; private loadDataViewNames = async (initialName?: string) => { @@ -297,9 +324,8 @@ export class DataViewEditorService { }; private loadTimestampFields = async () => { - if (this.matchedIndicesInternal$.getValue().exactMatchedIndices.length === 0) { - this.timestampFieldOptionsInternal$.next([]); - this.loadingTimestampFieldsInternal$.next(false); + if (this.state.matchedIndices.exactMatchedIndices.length === 0) { + this.updateState({ timestampFieldOptions: [], loadingTimestampFields: false }); return; } const currentLoadingTimestampFieldsIdx = ++this.currentLoadingTimestampFields; @@ -309,19 +335,18 @@ export class DataViewEditorService { }; if (this.type === INDEX_PATTERN_TYPE.ROLLUP) { getFieldsOptions.type = INDEX_PATTERN_TYPE.ROLLUP; - getFieldsOptions.rollupIndex = this.rollupIndexInternal$.getValue() || ''; + getFieldsOptions.rollupIndex = this.state.rollupIndexName || ''; } - let timestampOptions: TimestampOption[] = []; + let timestampFieldOptions: TimestampOption[] = []; try { - timestampOptions = await this.getTimestampOptionsForWildcardCached( + timestampFieldOptions = await this.getTimestampOptionsForWildcardCached( getFieldsOptions, this.requireTimestampField ); } finally { if (currentLoadingTimestampFieldsIdx === this.currentLoadingTimestampFields) { - this.timestampFieldOptionsInternal$.next(timestampOptions); - this.loadingTimestampFieldsInternal$.next(false); + this.updateState({ timestampFieldOptions, loadingTimestampFields: false }); } } }; From 1558a98286becd24c345643fd288f27b971fee84 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 6 Dec 2022 00:48:34 -0500 Subject: [PATCH 32/40] [api-docs] 2022-12-06 Daily api_docs build (#147063) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/178 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.devdocs.json | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.devdocs.json | 12 +- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_chat.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.devdocs.json | 4 +- api_docs/core.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.devdocs.json | 32 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.devdocs.json | 48 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 10 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.devdocs.json | 30 + api_docs/discover.mdx | 4 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 31 + api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_content_management_inspector.mdx | 2 +- .../kbn_content_management_table_list.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- .../kbn_core_application_browser.devdocs.json | 4 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- .../kbn_core_injected_metadata_browser.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...core_saved_objects_api_server_internal.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_get_repo_files.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.devdocs.json | 175 ++- api_docs/kbn_handlebars.mdx | 7 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_peggy.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- ...ared_ux_avatar_user_profile_components.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_type_summarizer_core.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 16 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.devdocs.json | 16 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.devdocs.json | 14 + api_docs/saved_search.mdx | 4 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.devdocs.json | 117 ++- api_docs/threat_intelligence.mdx | 4 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_histogram.devdocs.json | 993 ++++++++++-------- api_docs/unified_histogram.mdx | 7 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 459 files changed, 1440 insertions(+), 970 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 35cb9e51738bd..ff19463641bdf 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index b7e44d37ad723..4a35439d40109 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index 6ee28ad0d4fa6..ce17371ced270 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -203,7 +203,7 @@ "label": "CHANGE_POINT_DETECTION_ENABLED", "description": [], "signature": [ - "false" + "true" ], "path": "x-pack/plugins/aiops/common/index.ts", "deprecated": false, diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 0b96503230180..9db17d6564262 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index e75dbc0726e3e..cf05c3d4a8c3d 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index daf3593733b1b..7c7df2c2ef1e9 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -3123,7 +3123,15 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/apm/sourcemaps\", undefined, ", + "<\"GET /api/apm/sourcemaps\", ", + "PartialC", + "<{ query: ", + "PartialC", + "<{ page: ", + "Type", + "; perPage: ", + "Type", + "; }>; }>, ", { "pluginId": "apm", "scope": "server", @@ -3133,7 +3141,7 @@ }, ", { artifacts: ", "ArtifactSourceMap", - "[]; } | undefined, ", + "[]; total: number; } | undefined, ", "APMRouteCreateOptions", ">; \"DELETE /internal/apm/settings/custom_links/{id}\": ", { diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index aadb0f7ea7b40..fb33ac4a26637 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index efd5619bd9e5f..831f5e5d75dfa 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 4922b59250705..5f14e199c7773 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index c8814d1f0b481..b4a93382f17aa 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 11913f7eb18c4..e6ae7fa670928 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index b3cb11d531bdc..7748405cb8dd2 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index e8e22329e6795..6d1072645643c 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index d4712ac8d827d..38f299744c356 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 8eac00f514e1b..21ad542bcd77a 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 1d00633aee123..9781902a75b67 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 9003fb0d6061f..196a3ebf739a0 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index cafcf8e280993..fa1bcf776d4d6 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 6f0a2860610a5..a8e106fcb7b8b 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -17724,7 +17724,7 @@ "section": "def-common.AppStatus", "text": "AppStatus" }, - " | undefined; searchable?: boolean | undefined; deepLinks?: ", + " | undefined; tooltip?: string | undefined; searchable?: boolean | undefined; deepLinks?: ", { "pluginId": "@kbn/core-application-browser", "scope": "common", @@ -17740,7 +17740,7 @@ "section": "def-common.AppNavLinkStatus", "text": "AppNavLinkStatus" }, - " | undefined; defaultPath?: string | undefined; tooltip?: string | undefined; }" + " | undefined; defaultPath?: string | undefined; }" ], "path": "packages/core/application/core-application-browser/src/application.ts", "deprecated": false, diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 68471b32aa02a..2c82717588c5d 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index dadf1f63e886b..cd6737258ea79 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index ef8be6167173d..545c36050f22c 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index f154d0fa280ae..9168f7f6429fd 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index 940b6a3e9e85b..49b2390727a5a 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -13125,6 +13125,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -13149,14 +13157,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -20827,6 +20827,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -20851,14 +20859,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index c064bfc03c59f..d198d95574253 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 621bc44c5e8f9..fc0ac649b12de 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 6d70af95ba6ad..15b32b4c7d379 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 2766984baf17f..08c21e497f700 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 9bb735896bed8..1b388650a7386 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index b50fdf2509b61..4328a1d062a1d 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 3d2fc4b3d5205..eccf7c5366fa6 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -287,6 +287,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -311,14 +319,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -8588,6 +8588,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -8612,14 +8620,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -15970,6 +15970,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -15994,14 +16002,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 6cc6fde66953c..e399aabd710a7 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index ee1d624a91ad6..afb22249768d9 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 8a160a85083f5..1f8ba6e1aa122 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -28,10 +28,10 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-saved-objects-common, savedObjects, embeddable, visualizations, dashboard, fleet, infra, canvas, graph, actions, alerting, enterpriseSearch, securitySolution, taskManager, savedSearch, ml, @kbn/core-saved-objects-server-internal | - | | | core, savedObjects, embeddable, visualizations, dashboard, fleet, infra, canvas, graph, actions, alerting, enterpriseSearch, securitySolution, taskManager, savedSearch, ml, @kbn/core-saved-objects-server-internal | - | | | discover, maps, monitoring | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | | | discover | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | | | data, discover, embeddable | - | | | advancedSettings, discover | - | | | advancedSettings, discover | - | @@ -88,7 +88,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-plugins-server-internal | - | | | spaces, security, alerting | 8.8.0 | | | spaces, security, actions, alerting, ml, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, securitySolution, snapshotRestore, transform, upgradeAssistant | 8.8.0 | -| | embeddable, discover, presentationUtil, dashboard, graph | 8.8.0 | +| | embeddable, presentationUtil, dashboard, discover, graph | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | | | @kbn/core-application-browser-internal, @kbn/core-application-browser-mocks, visualizations, dashboard, lens, maps, ml, securitySolution, security | 8.8.0 | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 9deb9360ff04c..8ca8a5c288905 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 8679a9f647f7b..800c6ecd38273 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 074b29711306b..6cc8a050865da 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 32ec559942db0..c2dc34959d5b0 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -628,6 +628,22 @@ "path": "src/plugins/discover/public/locator.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverAppLocatorParams.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [ + "\nBreakdown field" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/discover/public/locator.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1295,6 +1311,20 @@ "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 070a64996f84e..58335dd854878 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 98 | 0 | 81 | 4 | +| 100 | 0 | 82 | 4 | ## Client diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 56fe62af6d6f1..3faa50733265a 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 2a76a96804a22..b972c0f166e76 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index a5a9128ef430c..0f08c9373088e 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 89c8d5f45f978..1c25d847b99e2 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 4de8c4d032e48..51ab2b0bbcc61 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index e49f2d7e53275..40e1fd571a8d7 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 61ad3313eb95a..4ea55ef4ad838 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index b411d4e4891d7..47e36c70b1092 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 253eadf1cb87e..c98c67e26ebd5 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index ff50fb53d201a..54980395d540a 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 01e18dd5dec48..2ef98aa58496f 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index be7dae9da80ff..17756263a9a36 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index f25847ff5ef64..4703bf686e102 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 513dad27ba95e..56f4a0d5ffa0d 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index ae381334b767d..4540e673800ac 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 083042a6c5a03..29e876af2e085 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 198af07b19c6e..5cb0fdc2e8d90 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index e171c101bd676..25a9194b7fdc4 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index fb7303d996a75..47f8ce5c9c3f7 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 245646b8959f7..0eb8c9e8d98de 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index ab6fd1a1043d7..fa79f4d4769e1 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index ec27a5c43052b..c412c816d8d47 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index c2c82cd84b52b..d7499f356373c 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 0a1b130b4fc9f..065653ee0f558 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 6fc8cdb127c8b..0f649447b182c 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index b9b1ca5788abf..4e63b994fb9d2 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index b01ff441e5e06..334f957e480d1 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 3d5432b0a31d2..ce10a6d3a887a 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -15149,6 +15149,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE", + "type": "string", + "tags": [], + "label": "FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE", + "description": [], + "signature": [ + "\"kspm\"" + ], + "path": "x-pack/plugins/fleet/common/constants/epm.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.FLEET_CLOUD_SECURITY_POSTURE_PACKAGE", @@ -17629,6 +17644,22 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.appRoutesService.postHealthCheckPath", + "type": "Function", + "tags": [], + "label": "postHealthCheckPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 5c925df5577d3..1b92c59893390 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1025 | 3 | 920 | 19 | +| 1027 | 3 | 922 | 19 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index b8d03ba1968a7..9ab3b37ee0964 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index b9cf3d11bfe4c..b4e513b13febe 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 1e21620bdf5da..7c88b4c2d9494 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 4713683921aad..beaa6e117d095 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 526b68dc5b831..6130a5f4a0b2b 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index b5165854e001b..d3bf04c9aa359 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 0309894b0e6e0..dd02144506fac 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 213f065bcac77..6a5f7832fac3d 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index df62e74597705..c425c4cbc8c2f 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index bd3753b78a083..d4a709746abc1 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index b566637b29ad5..90f1047c1ff4f 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 23b81ee0841e6..65beb5bc8ec9a 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index ff7f16ff00ffe..d4117d431d084 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 06826b5a03b40..1257c600b388f 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 5cbd7ee00b153..acc0e843ccbf6 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index f464f8fd6d3ed..6a61e0d734e90 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 3e1858c37423b..eede385a167f7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 62835d61687b7..f05383c9823c9 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 534d8da1ae358..311054668f3ac 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 58c1f6bd99b3b..90b5fea1d2130 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 7a0baf0658468..9defe8f2a6888 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 163b1aa5462af..922b0c2d40f0b 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 9de8082d49d59..ae640a234c3b0 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index dba03edf15b29..6d77f5edbaaaa 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 5bc7ef5c98a8c..01996752e5152 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index e65860dfd525a..29892f3b08110 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 5f661d90710fc..04c8f83cd7f69 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index df554eabea809..a9df84629653a 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 14076ef8e8c43..a98c5902a066f 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index a230ca900c897..85def9b8eb464 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 82b26b3f84097..7fc9f150d8a7e 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 4bdbafd254949..757fa174d4af6 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 9af33948c0f2a..0a63152fb2b34 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_inspector.mdx b/api_docs/kbn_content_management_inspector.mdx index 0b897cab6c63a..0f53318ee7f90 100644 --- a/api_docs/kbn_content_management_inspector.mdx +++ b/api_docs/kbn_content_management_inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-inspector title: "@kbn/content-management-inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-inspector plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-inspector'] --- import kbnContentManagementInspectorObj from './kbn_content_management_inspector.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 03760617c39be..0413880a5a20b 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index df76e526c7265..5f11d8900c77f 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 57337e422aff1..0c89b30b55b82 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 1c9f57a304d9a..e83fcc8e3b3e5 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 871e12069392c..94d5e24bba39e 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index f32ecf3dc29a2..a05929d4e2c23 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index cc3d83f372a1a..d6ae00d0756d5 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.devdocs.json b/api_docs/kbn_core_application_browser.devdocs.json index a71db82bf7b24..3617d74cf3736 100644 --- a/api_docs/kbn_core_application_browser.devdocs.json +++ b/api_docs/kbn_core_application_browser.devdocs.json @@ -2184,7 +2184,7 @@ "section": "def-common.AppStatus", "text": "AppStatus" }, - " | undefined; searchable?: boolean | undefined; deepLinks?: ", + " | undefined; tooltip?: string | undefined; searchable?: boolean | undefined; deepLinks?: ", { "pluginId": "@kbn/core-application-browser", "scope": "common", @@ -2200,7 +2200,7 @@ "section": "def-common.AppNavLinkStatus", "text": "AppNavLinkStatus" }, - " | undefined; defaultPath?: string | undefined; tooltip?: string | undefined; }" + " | undefined; defaultPath?: string | undefined; }" ], "path": "packages/core/application/core-application-browser/src/application.ts", "deprecated": false, diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 5033a169dcf02..e5145430f88ce 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 26d7392c62b04..0991508cdcf47 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 0ebe31d76e3ff..f7a6b42eda25c 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 2f6688337e84e..266547c987504 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index e88fc92ec82cb..4d1fdfd8a2a48 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index fac20450e4e32..45a42aacb49f0 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index acf1b0fe41e05..5336232039151 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index cbdffad66653b..0819c4101f6c8 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index b629f46093d9a..45f98461dc187 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 8357b282b034c..a43d045650ae2 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index a5c6949619227..f5afda9768202 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index fd6aa6397b293..e889fd243af24 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index b1e30506010f3..c72d04653e0af 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 7837bde82055b..f5321874a5c44 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index db98473942a22..47a382543300f 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index b6eb764b65654..5eb2bc6d8e06f 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 3ef841bacd521..1017fcbf71a44 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index dafabc0178e58..7668cb8db8e3e 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index abd3a052fe528..95cb1ab00d50d 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 1ccbd3e0f25b2..8be14215cb77f 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 9d9e870e1d1cf..d77b7e99afa22 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 6db81dc03443f..a1d5b8e9656e3 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 6352ad37e12f4..16d05337094ba 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 5336c69fd3141..f9795671bf19a 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index e60ffb357e3d0..78943917d80bc 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 170449f12e17b..9b2a2dfcee9c6 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index d72a5a4e4c5ae..bf65db30c301c 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 53abde00f49e7..8614904ddbfb3 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index e968290c2c5ec..cce389eee0d61 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 135bfeeaf45d4..3c479a5108b30 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 890c1319f0d4a..4ac0e5816b528 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 0c1d2dfef5563..fefb775e4820d 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 5ebaeabad7c40..58198264711b2 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 346ac05425c77..ad2679338e83d 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 2073436dfbc20..84b57b013c071 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 8875e22085de6..ce531e597364f 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 285c80b58aa0d..bf2ab3df3b3bb 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 20e84971bbaeb..73d1d16382b47 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 37089aca5f92f..ab99ccbbaac38 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 49bf027f46392..cc40714a7680b 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 00cbc57734deb..d6e0440137555 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index e1467961d3c28..986e9be1b12e0 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 71674458c868d..7d435faba134e 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 076e25a167785..e8ca4f852365e 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 8aebc9f04de35..c99af5e477c49 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 5450362a4e3eb..61f3b26de33e3 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 89e7bfb242915..33bed741ec8c9 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index d0d96d2713325..20b34df3790ee 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index bcca5db2d888f..c231ae64a5c22 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 3c5032fa5d290..eec495f106c97 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 1aa2c302c338f..1f42dab2dd77e 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 6d13deb213594..9280594a7952e 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 3291abcc63189..c430f2d25a6b9 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index ec5e5ddb73cfb..cbf061df2f53b 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 54f396bf1871d..3a3a59cc24db1 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index b987e8f511929..5bc170371eac6 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 0142d26e7e54e..e14d3e5f6e225 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index c9366402e89e6..8df81c8485cb1 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index b5cb4de66a5ef..7c4f4a8d02b42 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index c5671547de01c..62651a2972515 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index e6753ff1d25a8..c09fc4edbe3b2 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index f7958c020352b..7157f3bcf7c9e 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index ab1bc3c638427..69a312c78dbc5 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 0d4cd4357ac8c..cef493bcc2cdf 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index ec2ac0945fb75..0b6f211d95bc5 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 0c2a296e2a98b..4fc87e2929b50 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index fa43d178111ee..fa6fae1003f6d 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index f2a1df75fd8da..96a39d2da03ef 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index a772dd8f069d9..93533bdce2805 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 9b08a633de28e..afdc9a15c78d1 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 8d20c91d4b51e..feec70aa08cf7 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index 98057ba22a9bb..05212d195af71 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index eee3b043b5a4a..99c361512f874 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index e39da73e85fa8..37c69e4448592 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index acd4b276dd0dc..f283a5d14c691 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 5c4b447d4ac59..92749a0a9851f 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 36efd26f66411..8e6cb70f3758c 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 2ab7080cb6969..69b47e4da2a5d 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 0db86d496843d..6b60ccd65f266 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 138f6f6f83f74..7b491127d8ba9 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index eae3289a0f9e6..2672ccd4642dc 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 042d84a16e0cb..b9267b4bf4170 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index e7f334baf97a4..527c5f5c41564 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 3e674504c3c6f..5169544aa6953 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 9a2cfde2d52e7..044e6f6da7e00 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 22555239054d7..7ea4dec41fdac 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 5da90a824cb8f..761ba08b2e4eb 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 3f0da8640e0ea..0d5d764a85494 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index c8298091e7539..2a34ed909d3dc 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 74e7dc011cd50..23c0901aa37bf 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index ed0fddb74aa82..4fb5c82446f37 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 6de014b2458dc..7ebee6af491fe 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 9b8e5c362f389..737b181e2eb03 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index d920417027462..f1d7c495a6f57 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 7ca888bdc078b..1bdc6c9737e53 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index ccebb02142dd4..f89d1a649fce6 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index a7aa45ee1f407..685ca3bb626e3 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 480f257a894c4..ab312dbcaf3b1 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index d60dce10c3933..41ea98eb389cf 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index a15e6cfe13344..7439bc59f65d7 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index f639b7ae23353..c51398cd2bc68 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 3a4e650bceea1..85093ab0de7c1 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index a750cd3b04e4f..7e2de2e82d43e 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 61e738d289ab6..e121bac91a981 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 7b974a237f164..e5d9c3b6b1183 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 07c33b4a3ba1d..e89adf7825fd8 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 610563cc849cf..c55cae140748f 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 0a92218f93246..266eeca5b7b17 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 2d9f305668084..3b7963337688c 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 62b4e0a0dd3a7..0f6ee09219fe1 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index e49782ef2fea3..6db3cf241e453 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index a2bfca20a4909..59d860f9e6e57 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index f6d52b03d09fd..fa63ef0e06e3e 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index e97000ba9ab0f..462cb0c15d7f0 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 231d4e8cb3758..8672c40d385f1 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index f00ba25ae949a..fc2c3b5aecbc1 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index f011225966c22..932721d1cfd43 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 9ac987ad095bb..4bdf38d3cfe86 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index ca73e30ccff21..c391e859f6e22 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 827ab074fd152..c2a5e83864c37 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index ed31f2e330914..13645b911006d 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index d96a05a1b7c5b..aff6802de0a30 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index b32487a505dfd..7078555ea75bf 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index b035d2ee545e7..2e683f68503be 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 91db591285132..597a1d3f506d1 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 7e7ba2331527b..faece7243f02e 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index efb1aa1220c93..0d23068a8e239 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 24676dcc46160..407949386ac57 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 3bb2714c882b1..af319b0b46dbf 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 30c4732e1367c..e13168ab66b71 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 7b7f37bcf51eb..fe488d2b9160b 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 562c6f168efdb..6588f3db40c35 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 69ab6a5337870..104a3882e38b0 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index e8cc812828372..7d2f98a1fbee6 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index fd0f46ed2c11b..9b66c108cd033 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 07e9b92bbbb56..870a165def94d 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index c610278b130b0..c9f981e689d73 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index da117e0e0261f..4ae0594ed8497 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 9f4860a5bac82..e917187cbd9d5 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 2f18534567445..bed23f998989f 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 437fc61b5033d..4641db206c3e5 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 327bc6d071174..5ee595e321734 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index bdbc7ba229908..1c8d8f92e5b30 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 95c06166a0079..6f8c214b8e5d8 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index f19999d637806..572ff6f3a8fb6 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 78f20c87c67bf..d3ca2440ecfd1 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index dc6ce4800f16f..80d06db6c0381 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index f77b08149db16..231419258159c 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index db0fa6e03c200..3ecdd330b90f9 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 998dc9d2121c9..0599f20d0690d 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 29d889f1ad8e9..36faa22dca4d7 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index e61ee84a9ddb8..cf2f7734574bc 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 36a8271719f53..eb8869751d6d6 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 3f30979f5d811..83f5465e0e22a 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index f955a497c5e89..9559b919787ac 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 1d376ac3102f3..bf4860207b72f 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index a3d5b4789313e..c457675b1ff65 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index f9c6cc1073c0d..a1f60fe69e4a5 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 55c65a4173543..78d178b0e85db 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index dd08509ddcdfa..2a0c01e78f487 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index ef6b4f28465df..0df1f66094a09 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index d839938b11804..5418d72188074 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 34178b090e688..eb56f7fb40595 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index feb04a55d5f09..cf2a8683c5684 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 549b6234eaf21..72267a4b32c50 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.devdocs.json b/api_docs/kbn_handlebars.devdocs.json index 440a27d24ef64..e1233a052e2cb 100644 --- a/api_docs/kbn_handlebars.devdocs.json +++ b/api_docs/kbn_handlebars.devdocs.json @@ -49,7 +49,71 @@ "initialIsOpen": false } ], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorsHash", + "type": "Interface", + "tags": [], + "label": "DecoratorsHash", + "description": [], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorsHash.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[name: string]: DecoratorFunction", + "description": [], + "signature": [ + "[name: string]: ", + { + "pluginId": "@kbn/handlebars", + "scope": "common", + "docId": "kibKbnHandlebarsPluginApi", + "section": "def-common.DecoratorFunction", + "text": "DecoratorFunction" + } + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.HelpersHash", + "type": "Interface", + "tags": [], + "label": "HelpersHash", + "description": [], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.HelpersHash.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[name: string]: HelperDelegate", + "description": [], + "signature": [ + "[name: string]: Handlebars.HelperDelegate" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ { @@ -69,6 +133,113 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction", + "type": "Type", + "tags": [], + "label": "DecoratorFunction", + "description": [ + "\nAccording to the [decorator docs]{@link https://github.com/handlebars-lang/handlebars.js/blob/4.x/docs/decorators-api.md},\na decorator will be called with a different set of arugments than what's actually happening in the upstream code.\nSo here I assume that the docs are wrong and that the upstream code is correct. In reality, `context` is the last 4\ndocumented arguments rolled into one object." + ], + "signature": [ + "(prog: Handlebars.TemplateDelegate, props: Record, container: Container, options: any) => any" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1", + "type": "Function", + "tags": [], + "label": "prog", + "description": [], + "signature": [ + "Handlebars.TemplateDelegate" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1.$1", + "type": "Uncategorized", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "T" + ], + "path": "node_modules/handlebars/types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "Handlebars.RuntimeOptions | undefined" + ], + "path": "node_modules/handlebars/types/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$2", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$3", + "type": "Object", + "tags": [], + "label": "container", + "description": [], + "signature": [ + "Container" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$4", + "type": "Any", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/handlebars", "id": "def-common.ExtendedCompileOptions", @@ -96,7 +267,7 @@ "\nSupported Handlebars runtime options\n\nThis is a subset of all the runtime options supported by the upstream\nHandlebars module." ], "signature": [ - "{ data?: any; helpers?: { [name: string]: Function; } | undefined; blockParams?: any[] | undefined; }" + "{ data?: any; helpers?: { [name: string]: Function; } | undefined; blockParams?: any[] | undefined; decorators?: { [name: string]: Function; } | undefined; }" ], "path": "packages/kbn-handlebars/index.ts", "deprecated": false, diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index ee8dccec4971f..aaa32ce7c2956 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 6 | 0 | 0 | 0 | +| 17 | 1 | 8 | 0 | ## Common @@ -31,6 +31,9 @@ Contact [Owner missing] for questions regarding this plugin. ### Functions +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index dbf271baf02b3..6b1ff10552ff7 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index dff0a8b48d1c2..3dc202feb5468 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 38b31abf694e6..5787c0a64b061 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 5aace52619243..2f48f3535cbf0 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 1031e37ef30a4..7f601a4e6b157 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 4c43b131c0fd5..dac104a2e6207 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 1db9920b2cf66..921b776cf6d2f 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 3cc502815cf80..5270da2a8f613 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 3b0e372a30b09..172d157c6b878 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 2fc96bbef5229..31bf1187bb828 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index d85e2a2619de3..6a183876cb3df 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 74ab2e5c4a1f6..6b281e82d195b 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 4eaca6950214e..889cab6af3046 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 7081cd521dcb1..03ef626fe2ec5 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index c684962629a92..493c6fd536809 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 96766369fee16..270b052d1f45a 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 786b5b7cbea4a..f6be64a927aa4 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 7634c0d7b6ba0..d7288b6ddeacb 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 189d6f84ed060..80af6c1ace908 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 440e740af410a..bb878933973a2 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 66bef7439fa56..d684a319e2944 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 92f5c613a00c2..fb14195a42224 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 1d4971facb596..2e7b88625fd76 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index ac62e1e2895ec..c545b16c76e6b 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_peggy.mdx b/api_docs/kbn_peggy.mdx index d306b5779d68c..4a87f715dd78c 100644 --- a/api_docs/kbn_peggy.mdx +++ b/api_docs/kbn_peggy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-peggy title: "@kbn/peggy" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/peggy plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/peggy'] --- import kbnPeggyObj from './kbn_peggy.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index f81bbfda78423..57dcb6021e950 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 254920b626d40..9c796ba3c04ad 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 3ba442ea13bbc..de87b3df787ec 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 3f149e26cb8ba..8ee50b467ce60 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index f7e5859915e14..8ccf71cb57864 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index efd9928a5eff0..6736b2fd24754 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 4f1fa212d50e8..58c892f9ea5d1 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 2a26cbfdc4555..2a67b8f0b2a45 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index a42c49929a791..9ddc1a20ad2b5 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 88e8d2192f697..bf5dccc0e220b 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index ba3ad777e0e2d..3083b3254d881 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 913ec2b0cc0aa..f6a76b3a11330 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 11aafba54782a..bf51768f895cd 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 5ad7cfc9ab73f..b4a088e907489 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 92ef42d6918e2..5c9e710eab355 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 78ee660eb589d..184aae4efbdec 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 8b7c90d1d01d9..e8f2fd2f8a0f7 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index aa21a7c238056..a1cf9ab583b8c 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 36b0b0d0d018f..110857778b1fb 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index f98517347d5a0..bef2cb875a16d 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 2caf5060261c6..b7a7096ffbca7 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index abd85654608a1..6a1e9117265c4 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 608649bb066a4..e04a04c425a8f 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 874ee5b0c44e1..db6669b2c2c82 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index b1593e3d818b5..5a952d9c12768 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index b24187b311f11..975b27be5c27b 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index e8ebf35716f0d..d7d9bcf18c15a 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 2a9c776b00980..3aaeb39134631 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 6a5441a914f9d..92bad13340a97 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 5745cb3a16ee1..b7947a169a085 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 611b3e4cef451..70f22a645a033 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 8c372677e8b5e..3e77af0a80a2a 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 5821faf13b307..e9602d0f013ca 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 5729fc4768336..5f23b2f93f934 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index ae95ba2977418..efb441df915b6 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 64678f5c61355..e857d341cedae 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index b6be7817993f6..430f2cc900a82 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 5e55614849f64..e2854a67bfab8 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 4083540862bfe..644155759d1c7 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 8f59630337983..ec169705ca905 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index ee4872bfa4c20..51be49cf40b2c 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 53ec773cad647..855b42b2d5a66 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 39dafd9ae6b0e..49ec03b16234b 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 0ffe08e566309..5d3658dee5d49 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 55b955b9892c7..41d50fc164b8e 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index ef3aa7ed2622b..1cfb3c821f08c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index d97ac223bb4e6..895228de33167 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 03aaf670dbb8d..b8a0f2f427199 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index c3e1356aa89d9..a99824e974139 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index ad31f775ac700..b4a093c4eef94 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index d62135c7360cf..c1dcdb87f1cf8 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index e803cb5696067..5c7191ae761db 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index ca6de913b19eb..7a1fdec933db4 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 892b5bd184fa7..f05ddc5cf3d3a 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 4de29152ca4f6..76be341384b9f 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index ac621f53389b7..8e2b4ab96a3c1 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 71af52c9c8492..b7123b3a3cd72 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index e53ac5c57b932..55125706f1495 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 7bc1c7d26036c..ab0da30ffe19e 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 95809f532c6cf..095cd3b29e241 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 2e3b994e325f8..a7540897610d3 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 6386f509a3f49..e2ed020d653fc 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 30229d6d0a7ee..0493f6cf49de1 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index f10236d9d9e69..bbd7d580bc8ed 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 832e7f7a66253..3f50aa6eb4492 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 4ccc1f5569055..24b0aa2b2ac0b 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 76813f325d84f..9b444b117757a 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 8a399563252c9..4fb251e15c4a1 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 45c9c2c248ba8..5fd856539bbe7 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 98eb46f972bf3..7cad7bea538cb 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index b84900c98c29f..dd3c6057d0e52 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 6e0ac44e51e06..79d2d7563d148 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 4ff67a40bb37c..3950e617fc4a8 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index a8005d204d6c7..2b91876286436 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 6b09a72ddce67..db31d2c7eeb7b 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 71ef60a2480eb..1ac8cf70546aa 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index fb3476029d52d..58195dbec63f8 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 68e198da745fc..ed62483f69f94 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 472677e90bfef..c495abb76eedb 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 874a2d705085f..a0a3f2d6cbcb4 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index ec8e54b2f702c..18b98ee83d16a 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 676a16e7d633e..6b5f8816ff972 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 9e5268aacf139..4a273553298a6 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index c7d9a7595e25c..dc3fbbf30d5af 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 5e47ce98a20bb..ac739e788c61e 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 84442f0310543..099b953cf7274 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index dd6a83deb3657..a4a5fbaa4924d 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 4102367483464..3be720e7fca50 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 80d537922a299..e3962d6ab632c 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 6e3fb651a4008..374a530ff8309 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 4131dd937d40d..64b959f6bbf39 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index c3c8b23a530d2..c91506cb927e1 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 3d47d9ca48dac..3fb8911bcc351 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 39712cda8164a..079c9e8160afc 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 20ebb396243f1..8d768b4f7450e 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 11a933b3f2a73..b707bba302189 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 7fff0e8b6836c..4d680a6dcea18 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index fecb204330d39..5f8c939fcde4e 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 98fc486341cd6..25f52f331133e 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index ac40e22a875ff..0666c62f78f5d 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 5bf77bfdd1c3b..7dcaa3a357e84 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 33840 | 519 | 23574 | 1149 | +| 33860 | 520 | 23578 | 1149 | ## Plugin Directory @@ -59,7 +59,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 1021 | 0 | 227 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 28 | 3 | 24 | 1 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 98 | 0 | 81 | 4 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 100 | 0 | 82 | 4 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds embeddables service to Kibana | 510 | 6 | 410 | 4 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | @@ -87,7 +87,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 252 | 1 | 45 | 5 | | | [@elastic/kibana-global-experience](https://github.com/orgs/elastic/teams/@elastic/kibana-global-experience) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1025 | 3 | 920 | 19 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1027 | 3 | 922 | 19 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -137,7 +137,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 130 | 0 | 117 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 79 | 0 | 73 | 3 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 98 | 0 | 50 | 1 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 44 | 0 | 44 | 1 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 45 | 0 | 45 | 1 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 32 | 0 | 13 | 0 | | | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 4 | | searchprofiler | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | @@ -155,7 +155,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 31 | 0 | 26 | 6 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 1 | 0 | 1 | 0 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 11 | 0 | 10 | 0 | -| | [Protections Experience Team](https://github.com/orgs/elastic/teams/protections-experience) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 26 | 0 | 8 | 3 | +| | [Protections Experience Team](https://github.com/orgs/elastic/teams/protections-experience) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 34 | 0 | 14 | 3 | | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 462 | 1 | 350 | 33 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | @@ -163,7 +163,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 133 | 2 | 92 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 206 | 0 | 142 | 9 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 215 | 0 | 203 | 7 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 56 | 0 | 29 | 0 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 52 | 0 | 15 | 0 | | | [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 134 | 2 | 106 | 18 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | urlDrilldown | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | @@ -388,7 +388,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 1 | 0 | 0 | 0 | | | [Owner missing] | - | 3 | 0 | 0 | 0 | | | [Owner missing] | - | 23 | 0 | 21 | 1 | -| | [Owner missing] | - | 6 | 0 | 0 | 0 | +| | [Owner missing] | - | 17 | 1 | 8 | 0 | | | [Owner missing] | - | 3 | 0 | 3 | 0 | | | Kibana Core | - | 1 | 0 | 1 | 0 | | | [Owner missing] | - | 32 | 0 | 22 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 003701a990b50..85f6485348562 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 2025fdf3ac636..af66d2ac52e8d 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 27edc97dd18f7..b09b8bec09e5e 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index e5a64a581efaf..d121c901fd081 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 8bcc5e3739977..810a2537f3cf3 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 224d627abe557..a4c65e081973e 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 73c792df5cf52..7d67a6ae310b9 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.devdocs.json b/api_docs/saved_objects.devdocs.json index 46665808b0549..0762363169d52 100644 --- a/api_docs/saved_objects.devdocs.json +++ b/api_docs/saved_objects.devdocs.json @@ -631,14 +631,6 @@ "plugin": "embeddable", "path": "src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" - }, { "plugin": "presentationUtil", "path": "src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx" @@ -655,6 +647,14 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/application/top_nav/save_modal.tsx" }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/components/save_modal.tsx" diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 03a61be04bc4c..fd36a83407f44 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 4715ef515e006..7ac14f75e2ff4 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index f6bb3d0104094..6f2a973f3465c 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 7bee2622c16cb..28366f90e3a50 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 075a3084ed7a4..b0e43505cb269 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.devdocs.json b/api_docs/saved_search.devdocs.json index 8b7345d50d881..ba9542747b9ab 100644 --- a/api_docs/saved_search.devdocs.json +++ b/api_docs/saved_search.devdocs.json @@ -819,6 +819,20 @@ "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "savedSearch", + "id": "def-public.SavedSearch.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 051ef4af78a9b..61864a66a5a26 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 44 | 0 | 44 | 1 | +| 45 | 0 | 45 | 1 | ## Client diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index d95bc4d21b825..fda614bc83a44 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 817baa141b5e5..f9cc541b394da 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 73874eb06b30b..3d4fc14cd9a44 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 56bcf83cf575e..b01233eb7b862 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 38827562d9c48..a6ec7b973cd73 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 6f061d57edd5f..469b39680ac01 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index a1def6adedad1..4f774c08218d7 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 27d0d0c358f65..1697ab8495843 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 75462919e4130..77172023a15c2 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 3100e1efe31bc..3a492d7473f39 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 862b3bcaafa42..b1c3e3324973d 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index a1d3e34a48749..0a25aa3877b44 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 54f517d722f7c..9898ba4ec976f 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 1486ff1ea3f4e..cacc0a540af38 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 451fd81735c41..31fb7d6dc7a9e 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.devdocs.json b/api_docs/threat_intelligence.devdocs.json index 537c8c1268807..bf7f44448dd5f 100644 --- a/api_docs/threat_intelligence.devdocs.json +++ b/api_docs/threat_intelligence.devdocs.json @@ -222,10 +222,10 @@ }, { "parentPluginId": "threatIntelligence", - "id": "def-public.SecuritySolutionPluginContext.getSecuritySolutionStore", + "id": "def-public.SecuritySolutionPluginContext.securitySolutionStore", "type": "Object", "tags": [], - "label": "getSecuritySolutionStore", + "label": "securitySolutionStore", "description": [ "\nSecurity Solution store" ], @@ -389,6 +389,119 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery", + "type": "Function", + "tags": [], + "label": "registerQuery", + "description": [ + "\nRegister query in security solution store for tracking and centralized refresh support" + ], + "signature": [ + "(query: { id: string; loading: boolean; refetch: VoidFunction; }) => void" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.loading", + "type": "boolean", + "tags": [], + "label": "loading", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.refetch", + "type": "Function", + "tags": [], + "label": "refetch", + "description": [], + "signature": [ + "VoidFunction" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery", + "type": "Function", + "tags": [], + "label": "deregisterQuery", + "description": [ + "\nDeregister stale query" + ], + "signature": [ + "(query: { id: string; }) => void" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery.$1", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery.$1.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 6b963ca8e5e98..0e3075a724a1e 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Protections Experience Team](https://github.com/orgs/elastic/teams/prot | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 26 | 0 | 8 | 3 | +| 34 | 0 | 14 | 3 | ## Client diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 4d0eb8d0ff088..804656a3d20f1 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 88e76a329ba17..27fc618bceffe 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 4489575b95252..69ddb5c1093bf 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 20260b3449ab0..5fa67581c820d 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 8daacbbbc6900..a80c3ff9fb9df 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 1e744a9606b72..6ed9dc3725a5a 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.devdocs.json b/api_docs/unified_histogram.devdocs.json index 5ea1d379e5aea..7a881fb33eed3 100644 --- a/api_docs/unified_histogram.devdocs.json +++ b/api_docs/unified_histogram.devdocs.json @@ -3,253 +3,6 @@ "client": { "classes": [], "functions": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData", - "type": "Function", - "tags": [], - "label": "buildChartData", - "description": [ - "\nConvert the response from the chart request into a format that can be used\nby the unified histogram chart. The returned object should be used to update\n{@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}." - ], - "signature": [ - "({ data, dataView, timeInterval, response, }: { data: ", - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - }, - "; dataView: ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - "; timeInterval?: string | undefined; response?: ", - "SearchResponse", - "> | undefined; }) => { bucketInterval?: undefined; chartData?: undefined; } | { bucketInterval: ", - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramBucketInterval", - "text": "UnifiedHistogramBucketInterval" - }, - " | undefined; chartData: ", - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramChartData", - "text": "UnifiedHistogramChartData" - }, - "; }" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1", - "type": "Object", - "tags": [], - "label": "{\n data,\n dataView,\n timeInterval,\n response,\n}", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - } - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.timeInterval", - "type": "string", - "tags": [], - "label": "timeInterval", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.response", - "type": "Object", - "tags": [], - "label": "response", - "description": [], - "signature": [ - "SearchResponse", - "> | undefined" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs", - "type": "Function", - "tags": [], - "label": "getChartAggConfigs", - "description": [ - "\nHelper function to get the agg configs required for the unified histogram chart request" - ], - "signature": [ - "({\n dataView,\n timeInterval,\n data,\n}: { dataView: ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - "; timeInterval: string; data: ", - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - }, - "; }) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.AggConfigs", - "text": "AggConfigs" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1", - "type": "Object", - "tags": [], - "label": "{\n dataView,\n timeInterval,\n data,\n}", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.timeInterval", - "type": "string", - "tags": [], - "label": "timeInterval", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayout", @@ -296,12 +49,12 @@ "interfaces": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval", + "id": "def-public.UnifiedHistogramBreakdownContext", "type": "Interface", "tags": [], - "label": "UnifiedHistogramBucketInterval", + "label": "UnifiedHistogramBreakdownContext", "description": [ - "\nThe bucketInterval object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.bucketInterval}" + "\nContext object for the histogram breakdown" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -309,41 +62,22 @@ "children": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.scaled", - "type": "CompoundType", - "tags": [], - "label": "scaled", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.description", - "type": "string", + "id": "def-public.UnifiedHistogramBreakdownContext.field", + "type": "Object", "tags": [], - "label": "description", - "description": [], - "signature": [ - "string | undefined" + "label": "field", + "description": [ + "\nThe field used for the breakdown" ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.scale", - "type": "number", - "tags": [], - "label": "scale", - "description": [], "signature": [ - "number | undefined" + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -365,22 +99,6 @@ "deprecated": false, "trackAdoption": false, "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.status", - "type": "CompoundType", - "tags": [], - "label": "status", - "description": [ - "\nThe fetch status of the chart request" - ], - "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramChartContext.hidden", @@ -415,61 +133,15 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.bucketInterval", - "type": "Object", - "tags": [], - "label": "bucketInterval", - "description": [ - "\nThe bucketInterval object returned by {@link buildChartData}" - ], - "signature": [ - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramBucketInterval", - "text": "UnifiedHistogramBucketInterval" - }, - " | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [ - "\nThe chartData object returned by {@link buildChartData}" - ], - "signature": [ - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramChartData", - "text": "UnifiedHistogramChartData" - }, - " | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.error", - "type": "Object", + "id": "def-public.UnifiedHistogramChartContext.title", + "type": "string", "tags": [], - "label": "error", + "label": "title", "description": [ - "\nError from failed chart request" + "\nThe chart title -- sets the title property on the Lens chart input" ], "signature": [ - "Error | undefined" + "string | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -480,12 +152,12 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData", + "id": "def-public.UnifiedHistogramChartLoadEvent", "type": "Interface", "tags": [], - "label": "UnifiedHistogramChartData", + "label": "UnifiedHistogramChartLoadEvent", "description": [ - "\nThe chartData object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.data}" + "\nEmitted when the histogram loading status changes" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -493,27 +165,12 @@ "children": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.values", - "type": "Array", + "id": "def-public.UnifiedHistogramChartLoadEvent.complete", + "type": "boolean", "tags": [], - "label": "values", - "description": [], - "signature": [ - "{ x: number; y: number; }[]" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisOrderedValues", - "type": "Array", - "tags": [], - "label": "xAxisOrderedValues", - "description": [], - "signature": [ - "number[]" + "label": "complete", + "description": [ + "\nTrue if loading is complete" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -521,82 +178,39 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisFormat", + "id": "def-public.UnifiedHistogramChartLoadEvent.adapters", "type": "Object", "tags": [], - "label": "xAxisFormat", - "description": [], + "label": "adapters", + "description": [ + "\nInspector adapters for the request" + ], "signature": [ - "{ id?: string | undefined; params?: ", + "{ requests?: ", { - "pluginId": "fieldFormats", + "pluginId": "inspector", "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormatParams", - "text": "FieldFormatParams" + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" }, - "<{ pattern: string; }> | undefined; }" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.yAxisFormat", - "type": "Object", - "tags": [], - "label": "yAxisFormat", - "description": [], - "signature": [ - "{ id?: string | undefined; params?: ", + " | undefined; tables?: ", { - "pluginId": "fieldFormats", + "pluginId": "expressions", "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormatParams", - "text": "FieldFormatParams" + "docId": "kibExpressionsPluginApi", + "section": "def-common.TablesAdapter", + "text": "TablesAdapter" }, - "<{ pattern: string; }> | undefined; }" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisLabel", - "type": "string", - "tags": [], - "label": "xAxisLabel", - "description": [], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.yAxisLabel", - "type": "string", - "tags": [], - "label": "yAxisLabel", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.ordered", - "type": "Object", - "tags": [], - "label": "ordered", - "description": [], - "signature": [ - "Ordered" + " | undefined; expression?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionsInspectorAdapter", + "text": "ExpressionsInspectorAdapter" + }, + " | undefined; }" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -628,7 +242,14 @@ "\nThe fetch status of the hits count request" ], "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + }, + " | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -680,7 +301,9 @@ "type": "string", "tags": [], "label": "className", - "description": [], + "description": [ + "\nOptional class name to add to the layout container" + ], "signature": [ "string | undefined" ], @@ -694,7 +317,9 @@ "type": "Object", "tags": [], "label": "services", - "description": [], + "description": [ + "\nRequired services" + ], "signature": [ { "pluginId": "unifiedHistogram", @@ -708,6 +333,67 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [ + "\nThe current data view" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.lastReloadRequestTime", + "type": "number", + "tags": [], + "label": "lastReloadRequestTime", + "description": [ + "\nCan be updated to `Date.now()` to force a refresh" + ], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.request", + "type": "Object", + "tags": [], + "label": "request", + "description": [ + "\nContext object for requests made by unified histogram components -- optional" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramRequestContext", + "text": "UnifiedHistogramRequestContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayoutProps.hits", @@ -754,6 +440,29 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.breakdown", + "type": "Object", + "tags": [], + "label": "breakdown", + "description": [ + "\nContext object for the breakdown -- leave undefined to hide the breakdown" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramBreakdownContext", + "text": "UnifiedHistogramBreakdownContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayoutProps.resizeRef", @@ -846,12 +555,128 @@ "\nCallback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button" ], "signature": [ - "(() => void) | undefined" + "((lensAttributes: LensAttributes<\"lnsXY\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.XYState", + "text": "XYState" + }, + "> | LensAttributes<\"lnsPie\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.PieVisualizationState", + "text": "PieVisualizationState" + }, + "> | LensAttributes<\"lnsDatatable\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.DatatableVisualizationState", + "text": "DatatableVisualizationState" + }, + "> | LensAttributes<\"lnsLegacyMetric\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.LegacyMetricState", + "text": "LegacyMetricState" + }, + "> | LensAttributes<\"lnsMetric\", ", + "MetricVisualizationState", + "> | LensAttributes<\"lnsHeatmap\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.HeatmapVisualizationState", + "text": "HeatmapVisualizationState" + }, + "> | LensAttributes<\"lnsGauge\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.GaugeVisualizationState", + "text": "GaugeVisualizationState" + }, + "> | LensAttributes) => void) | undefined" ], "path": "src/plugins/unified_histogram/public/layout/layout.tsx", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onEditVisualization.$1", + "type": "CompoundType", + "tags": [], + "label": "lensAttributes", + "description": [], + "signature": [ + "LensAttributes<\"lnsXY\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.XYState", + "text": "XYState" + }, + "> | LensAttributes<\"lnsPie\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.PieVisualizationState", + "text": "PieVisualizationState" + }, + "> | LensAttributes<\"lnsDatatable\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.DatatableVisualizationState", + "text": "DatatableVisualizationState" + }, + "> | LensAttributes<\"lnsLegacyMetric\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.LegacyMetricState", + "text": "LegacyMetricState" + }, + "> | LensAttributes<\"lnsMetric\", ", + "MetricVisualizationState", + "> | LensAttributes<\"lnsHeatmap\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.HeatmapVisualizationState", + "text": "HeatmapVisualizationState" + }, + "> | LensAttributes<\"lnsGauge\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.GaugeVisualizationState", + "text": "GaugeVisualizationState" + }, + "> | LensAttributes" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], "returnComment": [] }, { @@ -921,6 +746,221 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onBreakdownFieldChange", + "type": "Function", + "tags": [], + "label": "onBreakdownFieldChange", + "description": [ + "\nCallback to update the breakdown field -- should set {@link UnifiedHistogramBreakdownContext.field} to breakdownField" + ], + "signature": [ + "((breakdownField: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onBreakdownFieldChange.$1", + "type": "Object", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange", + "type": "Function", + "tags": [], + "label": "onTotalHitsChange", + "description": [ + "\nCallback to update the total hits -- should set {@link UnifiedHistogramHitsContext.status} to status\nand {@link UnifiedHistogramHitsContext.total} to result" + ], + "signature": [ + "((status: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + }, + ", result?: number | Error | undefined) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange.$1", + "type": "Enum", + "tags": [], + "label": "status", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange.$2", + "type": "CompoundType", + "tags": [], + "label": "result", + "description": [], + "signature": [ + "number | Error | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartLoad", + "type": "Function", + "tags": [], + "label": "onChartLoad", + "description": [ + "\nCalled when the histogram loading status changes" + ], + "signature": [ + "((event: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartLoadEvent", + "text": "UnifiedHistogramChartLoadEvent" + }, + ") => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartLoad.$1", + "type": "Object", + "tags": [], + "label": "event", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartLoadEvent", + "text": "UnifiedHistogramChartLoadEvent" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramRequestContext", + "description": [ + "\nContext object for requests made by unified histogram components" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext.searchSessionId", + "type": "string", + "tags": [], + "label": "searchSessionId", + "description": [ + "\nCurrent search session ID" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext.adapter", + "type": "Object", + "tags": [], + "label": "adapter", + "description": [ + "\nThe adapter to use for requests (does not apply to Lens requests)" + ], + "signature": [ + { + "pluginId": "inspector", + "scope": "common", + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1045,24 +1085,81 @@ "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.lens", + "type": "Object", + "tags": [], + "label": "lens", + "description": [], + "signature": [ + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.LensPublicStart", + "text": "LensPublicStart" + } + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false } ], - "enums": [], - "misc": [ + "enums": [ { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramFetchStatus", - "type": "Type", + "type": "Enum", "tags": [], "label": "UnifiedHistogramFetchStatus", "description": [ "\nThe fetch status of a unified histogram request" ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramAdapters", + "type": "Type", + "tags": [], + "label": "UnifiedHistogramAdapters", + "description": [], "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + "{ requests?: ", + { + "pluginId": "inspector", + "scope": "common", + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" + }, + " | undefined; tables?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.TablesAdapter", + "text": "TablesAdapter" + }, + " | undefined; expression?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionsInspectorAdapter", + "text": "ExpressionsInspectorAdapter" + }, + " | undefined; }" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index d8f5d006d6f3a..516370395fbb4 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 29 | 0 | +| 52 | 0 | 15 | 0 | ## Client @@ -31,6 +31,9 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco ### Interfaces +### Enums + + ### Consts, variables and types diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 5a7a3a3144f19..541ddaa1d833a 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 425b495d1bb4f..c712e9aedc5b1 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index aea982fa14448..1b6f8246208a0 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index b271a6f33b7eb..558cc3e447e90 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 4935aa9b4080e..33f455584f77d 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 62661f10bdd88..ada62356443b5 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 8c4152612ae42..a8daaef1592a8 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 63d72602e1e46..c2925dadbc203 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 08d72e146afe1..b2cf964c6ceb6 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 9962adbfe713f..fa6224b4060bf 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 502d8c16af8df..1b25eee004e2b 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index b6af693ea1356..b10f3bb9f6da9 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index ca426dbf7c6cc..430151dc5c26f 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 05036a809a037..cdf56efe992a0 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 920d4621d93aa..2f6c080e9a626 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 27892ebc54ef3..879e5181b4c14 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-12-05 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 45430b1a09b025651784352f52020d481db2a3ed Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 6 Dec 2022 09:31:21 +0200 Subject: [PATCH 33/40] [Lens] Order date fields first on discover drilldown (#146786) ## Summary Closes https://github.com/elastic/kibana/issues/146442 Orders the date fields first when navigating from Lens to Discover. ![lens](https://user-images.githubusercontent.com/17003240/205071467-0ae8722c-533f-48ce-8905-08e6f0fad073.gif) ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../app_plugin/show_underlying_data.test.ts | 44 ++++++++++++++++++- .../public/app_plugin/show_underlying_data.ts | 25 ++++++++++- .../apps/lens/group2/show_underlying_data.ts | 4 +- .../group2/show_underlying_data_dashboard.ts | 2 +- 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts index c6f97c9670031..793064bd008fd 100644 --- a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts +++ b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts @@ -9,6 +9,7 @@ import { createMockDatasource } from '../mocks'; import { combineQueryAndFilters, getLayerMetaInfo } from './show_underlying_data'; import { Filter } from '@kbn/es-query'; import { DatasourcePublicAPI } from '../types'; +import { createMockedIndexPattern } from '../datasources/form_based/mocks'; describe('getLayerMetaInfo', () => { const capabilities = { @@ -174,7 +175,7 @@ describe('getLayerMetaInfo', () => { getOperationForColumnId: jest.fn(), getTableSpec: jest.fn(() => [{ columnId: 'col1', fields: ['bytes'] }]), getVisualDefaults: jest.fn(), - getSourceId: jest.fn(), + getSourceId: jest.fn(() => '1'), getMaxPossibleNumValues: jest.fn(), isTextBasedLanguage: jest.fn(() => false), getFilters: jest.fn(() => ({ @@ -187,13 +188,16 @@ describe('getLayerMetaInfo', () => { hasDefaultTimeField: jest.fn(() => true), }; mockDatasource.getPublicAPI.mockReturnValue(updatedPublicAPI); + const sampleIndexPatternsFromService = { + '1': createMockedIndexPattern(), + }; const { error, meta } = getLayerMetaInfo( mockDatasource, {}, // the publicAPI has been mocked, so no need for a state here { datatable1: { type: 'datatable', columns: [], rows: [] }, }, - {}, + sampleIndexPatternsFromService, undefined, capabilities ); @@ -214,6 +218,42 @@ describe('getLayerMetaInfo', () => { disabled: { kuery: [], lucene: [] }, }); }); + + it('should order date fields first', () => { + const mockDatasource = createMockDatasource('testDatasource'); + const updatedPublicAPI: DatasourcePublicAPI = { + datasourceId: 'formBased', + getOperationForColumnId: jest.fn(), + getTableSpec: jest.fn(() => [{ columnId: 'col1', fields: ['bytes', 'timestamp'] }]), + getVisualDefaults: jest.fn(), + getSourceId: jest.fn(() => '1'), + getMaxPossibleNumValues: jest.fn(), + isTextBasedLanguage: jest.fn(() => false), + getFilters: jest.fn(() => ({ + enabled: { + kuery: [[{ language: 'kuery', query: 'memory > 40000' }]], + lucene: [], + }, + disabled: { kuery: [], lucene: [] }, + })), + hasDefaultTimeField: jest.fn(() => true), + }; + mockDatasource.getPublicAPI.mockReturnValue(updatedPublicAPI); + const sampleIndexPatternsFromService = { + '1': createMockedIndexPattern(), + }; + const { meta } = getLayerMetaInfo( + mockDatasource, + {}, // the publicAPI has been mocked, so no need for a state here + { + datatable1: { type: 'datatable', columns: [], rows: [] }, + }, + sampleIndexPatternsFromService, + undefined, + capabilities + ); + expect(meta?.columns).toEqual(['timestamp', 'bytes']); + }); }); describe('combineQueryAndFilters', () => { it('should just return same query and filters if no fields or filters are in layer meta', () => { diff --git a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts index c6377fb76d03c..9a0c4a9ed70eb 100644 --- a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts +++ b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts @@ -59,6 +59,27 @@ interface LayerMetaInfo { >; } +const sortByDateFieldsFirst = ( + datasourceAPI: DatasourcePublicAPI, + fields: string[], + indexPatterns: IndexPatternMap +) => { + const dataViewId = datasourceAPI.getSourceId(); + if (!dataViewId) return; + + // for usability reasons we want to order the date fields first + // the fields order responds to the columns order in Discover + const dateFieldsFirst = fields.reduce((acc: string[], fieldName) => { + const field = indexPatterns[dataViewId]?.getFieldByName(fieldName); + if (field?.type === 'date') { + return [fieldName, ...acc]; + } + return [...acc, fieldName]; + }, []); + + return dateFieldsFirst; +}; + export function getLayerMetaInfo( currentDatasource: Datasource | undefined, datasourceState: unknown, @@ -137,10 +158,12 @@ export function getLayerMetaInfo( } const uniqueFields = [...new Set(columnsWithNoTimeShifts.map(({ fields }) => fields).flat())]; + const dateFieldsFirst = sortByDateFieldsFirst(datasourceAPI, uniqueFields, indexPatterns); + return { meta: { id: datasourceAPI.getSourceId()!, - columns: uniqueFields, + columns: dateFieldsFirst ?? uniqueFields, filters: filtersOrError, }, error: undefined, diff --git a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts index 5c73e6ca7c288..41e327234009b 100644 --- a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts @@ -44,7 +44,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.existOrFail('unifiedHistogramChart'); // check the table columns const columns = await PageObjects.discover.getColumnHeaders(); - expect(columns).to.eql(['extension.raw', '@timestamp', 'bytes']); + expect(columns).to.eql(['@timestamp', 'extension.raw', 'bytes']); await browser.closeCurrentWindow(); await browser.switchToWindow(lensWindowHandler); }); @@ -142,7 +142,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.existOrFail('unifiedHistogramChart'); // check the columns const columns = await PageObjects.discover.getColumnHeaders(); - expect(columns).to.eql(['extension.raw', '@timestamp', 'memory']); + expect(columns).to.eql(['@timestamp', 'extension.raw', 'memory']); // check the query expect(await queryBar.getQueryString()).be.eql( '( ( bytes > 2000 ) AND ( ( extension.raw: "css" ) OR ( extension.raw: "gif" ) OR ( extension.raw: "jpg" ) ) )' diff --git a/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts index a89b4c8727bc1..46fdc94879d03 100644 --- a/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts @@ -50,7 +50,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.existOrFail('unifiedHistogramChart'); // check the table columns const columns = await PageObjects.discover.getColumnHeaders(); - expect(columns).to.eql(['ip', '@timestamp', 'bytes']); + expect(columns).to.eql(['@timestamp', 'ip', 'bytes']); await browser.closeCurrentWindow(); await browser.switchToWindow(dashboardWindowHandle); From 6df9aca36a8852f305591ef9f8bff910f5f5533f Mon Sep 17 00:00:00 2001 From: Elastic Machine Date: Tue, 6 Dec 2022 02:57:37 -0500 Subject: [PATCH 34/40] [main] Sync bundled packages with Package Storage (#146821) Automated by https://internal-ci.elastic.co/job/package_storage/job/sync-bundled-packages-job/job/main/784/ Co-authored-by: apmmachine Co-authored-by: Kyle Pollich --- fleet_packages.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fleet_packages.json b/fleet_packages.json index 10f7e5d8b0994..3b33407ef4aeb 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -20,7 +20,7 @@ [ { "name": "apm", - "version": "8.6.0-preview-1663775281", + "version": "8.7.0-preview-1669303673", "forceAlignStackVersion": true }, { @@ -37,6 +37,6 @@ }, { "name": "synthetics", - "version": "0.10.3" + "version": "0.11.4" } -] +] \ No newline at end of file From 0d2c7e54988fcef3b1b7ee98071c0d508ed9b8b9 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 6 Dec 2022 09:08:35 +0100 Subject: [PATCH 35/40] [Discover] Fix flaky runtime field test (#147006) Closes https://github.com/elastic/kibana/issues/146996 https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1630 --- test/functional/page_objects/discover_page.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index a7181b9490314..624e728a0d384 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -397,14 +397,14 @@ export class DiscoverPageObject extends FtrService { public async editField(field: string) { await this.retry.try(async () => { - await this.testSubjects.click(`field-${field}`); + await this.clickFieldListItem(field); await this.testSubjects.click(`discoverFieldListPanelEdit-${field}`); await this.find.byClassName('indexPatternFieldEditor__form'); }); } public async removeField(field: string) { - await this.testSubjects.click(`field-${field}`); + await this.clickFieldListItem(field); await this.testSubjects.click(`discoverFieldListPanelDelete-${field}`); await this.testSubjects.existOrFail('runtimeFieldDeleteConfirmModal'); await this.fieldEditor.confirmDelete(); From 61930b7ef92a1c652f2c2e1c7f49c6da1988f6ac Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 6 Dec 2022 09:09:21 +0100 Subject: [PATCH 36/40] [Discover] Fix flaky "visualize in lens" test (#146863) Closes https://github.com/elastic/kibana/issues/141616 https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1615 --- test/functional/page_objects/discover_page.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 624e728a0d384..d6c12c9bb9e43 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -506,14 +506,18 @@ export class DiscoverPageObject extends FtrService { ); } - public async clickFieldListItem(field: string) { - await this.testSubjects.click(`field-${field}`); - + public async waitUntilFieldPopoverIsOpen() { await this.retry.waitFor('popover is open', async () => { return Boolean(await this.find.byCssSelector('[data-popover-open="true"]')); }); } + public async clickFieldListItem(field: string) { + await this.testSubjects.click(`field-${field}`); + + await this.waitUntilFieldPopoverIsOpen(); + } + public async clickFieldSort(field: string, text = 'Sort New-Old') { const isLegacyDefault = await this.useLegacyTable(); if (isLegacyDefault) { @@ -583,6 +587,7 @@ export class DiscoverPageObject extends FtrService { await field.click(); } + await this.waitUntilFieldPopoverIsOpen(); await this.testSubjects.click(`fieldVisualize-${fieldName}`); await this.header.waitUntilLoadingHasFinished(); } From bacbd72dd6c623b3bba0e8a6c6f98c790806debe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 6 Dec 2022 10:22:45 +0100 Subject: [PATCH 37/40] [APM] Service map simplifications (#146536) These changes should make it simpler to add the search bar to the service map. --- x-pack/plugins/apm/server/index.ts | 2 +- .../routes/service_map/get_service_map.ts | 101 ++---------------- .../routes/service_map/get_service_stats.ts | 89 +++++++++++++++ .../service_map/get_trace_sample_ids.ts | 55 +++++----- .../apm/server/routes/service_map/route.ts | 7 +- .../observability/server/utils/queries.ts | 2 +- 6 files changed, 131 insertions(+), 125 deletions(-) create mode 100644 x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 17682706571cc..19b34766a1bf2 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -20,10 +20,10 @@ const configSchema = schema.object({ autoCreateApmDataView: schema.boolean({ defaultValue: true }), serviceMapEnabled: schema.boolean({ defaultValue: true }), serviceMapFingerprintBucketSize: schema.number({ defaultValue: 100 }), - serviceMapTraceIdBucketSize: schema.number({ defaultValue: 65 }), serviceMapFingerprintGlobalBucketSize: schema.number({ defaultValue: 1000, }), + serviceMapTraceIdBucketSize: schema.number({ defaultValue: 65 }), serviceMapTraceIdGlobalBucketSize: schema.number({ defaultValue: 6 }), serviceMapMaxTracesPerRequest: schema.number({ defaultValue: 50 }), ui: schema.object({ diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts index 35c422c53156e..fb1d0eed0a151 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts @@ -7,14 +7,7 @@ import { Logger } from '@kbn/core/server'; import { chunk } from 'lodash'; -import { rangeQuery, termsQuery } from '@kbn/observability-plugin/server'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { - AGENT_NAME, - SERVICE_ENVIRONMENT, - SERVICE_NAME, -} from '../../../common/es_fields/apm'; -import { environmentQuery } from '../../../common/utils/environment_query'; + import { withApmSpan } from '../../utils/with_apm_span'; import { MlClient } from '../../lib/helpers/get_ml_client'; import { @@ -24,44 +17,41 @@ import { import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; import { transformServiceMapResponses } from './transform_service_map_responses'; -import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; -import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; -import { ServiceGroup } from '../../../common/service_groups'; -import { serviceGroupQuery } from '../../lib/service_group_query'; import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; import { APMConfig } from '../..'; +import { getServiceStats } from './get_service_stats'; export interface IEnvOptions { mlClient?: MlClient; config: APMConfig; apmEventClient: APMEventClient; - serviceNames?: string[]; + serviceName?: string; environment: string; searchAggregatedTransactions: boolean; logger: Logger; start: number; end: number; - serviceGroup: ServiceGroup | null; + serviceGroupKuery?: string; } async function getConnectionData({ config, apmEventClient, - serviceNames, + serviceName, environment, start, end, - serviceGroup, + serviceGroupKuery, }: IEnvOptions) { return withApmSpan('get_service_map_connections', async () => { const { traceIds } = await getTraceSampleIds({ config, apmEventClient, - serviceNames, + serviceName, environment, start, end, - serviceGroup, + serviceGroupKuery, }); const chunks = chunk(traceIds, config.serviceMapMaxTracesPerRequest); @@ -101,79 +91,8 @@ async function getConnectionData({ }); } -async function getServicesData( - options: IEnvOptions & { maxNumberOfServices: number } -) { - const { - environment, - apmEventClient, - searchAggregatedTransactions, - start, - end, - maxNumberOfServices, - serviceGroup, - } = options; - const params = { - apm: { - events: [ - getProcessorEventForTransactions(searchAggregatedTransactions), - ProcessorEvent.metric as const, - ProcessorEvent.error as const, - ], - }, - body: { - track_total_hits: false, - size: 0, - query: { - bool: { - filter: [ - ...rangeQuery(start, end), - ...environmentQuery(environment), - ...termsQuery(SERVICE_NAME, ...(options.serviceNames ?? [])), - ...serviceGroupQuery(serviceGroup), - ], - }, - }, - aggs: { - services: { - terms: { - field: SERVICE_NAME, - size: maxNumberOfServices, - }, - aggs: { - agent_name: { - terms: { - field: AGENT_NAME, - }, - }, - }, - }, - }, - }, - }; - - const response = await apmEventClient.search( - 'get_service_stats_for_service_map', - params - ); - - return ( - response.aggregations?.services.buckets.map((bucket) => { - return { - [SERVICE_NAME]: bucket.key as string, - [AGENT_NAME]: - (bucket.agent_name.buckets[0]?.key as string | undefined) || '', - [SERVICE_ENVIRONMENT]: - options.environment === ENVIRONMENT_ALL.value - ? null - : options.environment, - }; - }) || [] - ); -} - export type ConnectionsResponse = Awaited>; -export type ServicesResponse = Awaited>; +export type ServicesResponse = Awaited>; export function getServiceMap( options: IEnvOptions & { maxNumberOfServices: number } @@ -192,7 +111,7 @@ export function getServiceMap( const [connectionData, servicesData, anomalies] = await Promise.all([ getConnectionData(options), - getServicesData(options), + getServiceStats(options), anomaliesPromise, ]); diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts new file mode 100644 index 0000000000000..1f43a35d3b1ef --- /dev/null +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts @@ -0,0 +1,89 @@ +/* + * 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 { + kqlQuery, + rangeQuery, + termsQuery, +} from '@kbn/observability-plugin/server'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { + AGENT_NAME, + SERVICE_ENVIRONMENT, + SERVICE_NAME, +} from '../../../common/es_fields/apm'; +import { environmentQuery } from '../../../common/utils/environment_query'; +import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { IEnvOptions } from './get_service_map'; + +export async function getServiceStats({ + environment, + apmEventClient, + searchAggregatedTransactions, + start, + end, + maxNumberOfServices, + serviceGroupKuery, + serviceName, +}: IEnvOptions & { maxNumberOfServices: number }) { + const params = { + apm: { + events: [ + getProcessorEventForTransactions(searchAggregatedTransactions), + ProcessorEvent.metric as const, + ProcessorEvent.error as const, + ], + }, + body: { + track_total_hits: false, + size: 0, + query: { + bool: { + filter: [ + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...termsQuery(SERVICE_NAME, serviceName), + ...kqlQuery(serviceGroupKuery), + ], + }, + }, + aggs: { + services: { + terms: { + field: SERVICE_NAME, + size: maxNumberOfServices, + }, + aggs: { + agent_name: { + terms: { + field: AGENT_NAME, + }, + }, + }, + }, + }, + }, + }; + + const response = await apmEventClient.search( + 'get_service_stats_for_service_map', + params + ); + + return ( + response.aggregations?.services.buckets.map((bucket) => { + return { + [SERVICE_NAME]: bucket.key as string, + [AGENT_NAME]: + (bucket.agent_name.buckets[0]?.key as string | undefined) || '', + [SERVICE_ENVIRONMENT]: + environment === ENVIRONMENT_ALL.value ? null : environment, + }; + }) || [] + ); +} diff --git a/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts index d65e97c6988e5..42935dbdcda88 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts @@ -7,7 +7,11 @@ import Boom from '@hapi/boom'; import { sortBy, take, uniq } from 'lodash'; -import { rangeQuery } from '@kbn/observability-plugin/server'; +import { + kqlQuery, + rangeQuery, + termQuery, +} from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { @@ -18,62 +22,59 @@ import { } from '../../../common/es_fields/apm'; import { SERVICE_MAP_TIMEOUT_ERROR } from '../../../common/service_map'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { serviceGroupQuery } from '../../lib/service_group_query'; -import { ServiceGroup } from '../../../common/service_groups'; + import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; import { APMConfig } from '../..'; const MAX_TRACES_TO_INSPECT = 1000; export async function getTraceSampleIds({ - serviceNames, + serviceName, environment, config, apmEventClient, start, end, - serviceGroup, + serviceGroupKuery, }: { - serviceNames?: string[]; + serviceName?: string; environment: string; config: APMConfig; apmEventClient: APMEventClient; start: number; end: number; - serviceGroup: ServiceGroup | null; + serviceGroupKuery?: string; }) { const query = { bool: { - filter: [...rangeQuery(start, end), ...serviceGroupQuery(serviceGroup)], + filter: [ + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(serviceGroupKuery), + ...termQuery(SERVICE_NAME, serviceName), + ], }, }; - let events: ProcessorEvent[]; + const isGlobalServiceMap = !serviceName && !serviceGroupKuery; + let events = [ProcessorEvent.span, ProcessorEvent.transaction]; - const hasServiceNamesFilter = (serviceNames?.length ?? 0) > 0; - - if (hasServiceNamesFilter) { - query.bool.filter.push({ - terms: { [SERVICE_NAME]: serviceNames as string[] }, - }); - events = [ProcessorEvent.span, ProcessorEvent.transaction]; - } else { + // perf optimization that is only possible on the global service map with no filters + if (isGlobalServiceMap) { events = [ProcessorEvent.span]; query.bool.filter.push({ - exists: { - field: SPAN_DESTINATION_SERVICE_RESOURCE, - }, + exists: { field: SPAN_DESTINATION_SERVICE_RESOURCE }, }); } - query.bool.filter.push(...environmentQuery(environment)); + const fingerprintBucketSize = isGlobalServiceMap + ? config.serviceMapFingerprintGlobalBucketSize + : config.serviceMapFingerprintBucketSize; + + const traceIdBucketSize = isGlobalServiceMap + ? config.serviceMapTraceIdGlobalBucketSize + : config.serviceMapTraceIdBucketSize; - const fingerprintBucketSize = hasServiceNamesFilter - ? config.serviceMapFingerprintBucketSize - : config.serviceMapFingerprintGlobalBucketSize; - const traceIdBucketSize = hasServiceNamesFilter - ? config.serviceMapTraceIdBucketSize - : config.serviceMapTraceIdGlobalBucketSize; const samplerShardSize = traceIdBucketSize * 10; const params = { diff --git a/x-pack/plugins/apm/server/routes/service_map/route.ts b/x-pack/plugins/apm/server/routes/service_map/route.ts index 1cf4dd40afbcf..69f4422ad337a 100644 --- a/x-pack/plugins/apm/server/routes/service_map/route.ts +++ b/x-pack/plugins/apm/server/routes/service_map/route.ts @@ -7,7 +7,6 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; -import { compact } from 'lodash'; import { apmServiceGroupMaxNumberOfServices } from '@kbn/observability-plugin/common'; import { isActivePlatinumLicense } from '../../../common/license_check'; import { invalidLicenseMessage } from '../../../common/service_map'; @@ -129,8 +128,6 @@ const serviceMapRoute = createApmServerRoute({ uiSettingsClient.get(apmServiceGroupMaxNumberOfServices), ]); - const serviceNames = compact([serviceName]); - const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient, config, @@ -142,14 +139,14 @@ const serviceMapRoute = createApmServerRoute({ mlClient, config, apmEventClient, - serviceNames, + serviceName, environment, searchAggregatedTransactions, logger, start, end, maxNumberOfServices, - serviceGroup, + serviceGroupKuery: serviceGroup?.kuery, }); }, }); diff --git a/x-pack/plugins/observability/server/utils/queries.ts b/x-pack/plugins/observability/server/utils/queries.ts index b3d9c590e32b7..1e835fe02d2b0 100644 --- a/x-pack/plugins/observability/server/utils/queries.ts +++ b/x-pack/plugins/observability/server/utils/queries.ts @@ -60,7 +60,7 @@ export function rangeQuery( ]; } -export function kqlQuery(kql: string): estypes.QueryDslQueryContainer[] { +export function kqlQuery(kql?: string): estypes.QueryDslQueryContainer[] { if (!kql) { return []; } From 6d12ced52b554c8e6297372a4daf52ef26f134ac Mon Sep 17 00:00:00 2001 From: Marshall Main <55718608+marshallmain@users.noreply.github.com> Date: Tue, 6 Dec 2022 01:34:42 -0800 Subject: [PATCH 38/40] [Security Solution][Rules] Don't display new features tour if guided onboarding is active (#146902) Due to the location of the guided onboarding tour, it can overlap with the new features tour when a user is doing guided onboarding. This PR disables the new features tour if the user is in the middle of guided onboarding. There is still a remaining issue where after the user completes the 3 steps of the guided onboarding on the rules page, the `isGuideStepActive$` API returns `false` even though there is still a tooltip open for the `Continue with the guide` option. The new features tour overlaps with this option. ![image](https://user-images.githubusercontent.com/55718608/205739417-fd19930d-a9c5-41ea-8f78-3adb4451ca16.png) --- .../rules_table/alternative_tour/tour.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/tour.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/tour.tsx index 01118455fd642..0b250a3dfb34a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/tour.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/tour.tsx @@ -6,6 +6,8 @@ */ import { EuiText, EuiTourStep } from '@elastic/eui'; +import useObservable from 'react-use/lib/useObservable'; +import { of } from 'rxjs'; import React, { useCallback, useEffect, useState } from 'react'; import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '../../../../../../common/constants'; import { useKibana } from '../../../../../common/lib/kibana'; @@ -22,7 +24,15 @@ export const RulesPageTourComponent: React.FC = ({ children }) => { tourPopoverWidth: 300, }; - const { storage } = useKibana().services; + const { + storage, + guidedOnboarding: { guidedOnboardingApi }, + } = useKibana().services; + + const isGuidedOnboardingActive = useObservable( + guidedOnboardingApi?.isGuideStepActive$('security', 'rules') ?? of(false), + true + ); const [tourState, setTourState] = useState(() => { const restoredTourState = storage.get(NEW_FEATURES_TOUR_STORAGE_KEYS.RULE_MANAGEMENT_PAGE); @@ -54,7 +64,9 @@ export const RulesPageTourComponent: React.FC = ({ children }) => { return ( Date: Tue, 6 Dec 2022 10:37:46 +0100 Subject: [PATCH 39/40] Invalidate cache for rules, after add shared exception (#146979) ## Invalidate cache for rules, after adding shared exception Related: https://github.com/elastic/kibana/issues/146962 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/add_exception_flyout/index.test.tsx | 1 + .../components/add_exception_flyout/index.tsx | 4 ++++ .../public/exceptions/hooks/use_list_detail_view/index.ts | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx index d422c7c5ce6bf..e750b0ddc75bb 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx @@ -49,6 +49,7 @@ jest.mock('@kbn/securitysolution-hook-utils', () => ({ jest.mock('../../../rule_management/logic/use_rule'); jest.mock('@kbn/lists-plugin/public'); jest.mock('../../../rule_management/logic/use_find_rules'); +jest.mock('../../../rule_management/api/hooks/use_fetch_rule_by_id_query'); const mockGetExceptionBuilderComponentLazy = getExceptionBuilderComponentLazy as jest.Mock< ReturnType diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx index 9366dbd04a9e7..f031344631faa 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx @@ -53,6 +53,7 @@ import { useAddNewExceptionItems } from './use_add_new_exceptions'; import { enrichNewExceptionItems } from '../flyout_components/utils'; import { useCloseAlertsFromExceptions } from '../../logic/use_close_alerts'; import { ruleTypesThatAllowLargeValueLists } from '../../utils/constants'; +import { useInvalidateFetchRuleByIdQuery } from '../../../rule_management/api/hooks/use_fetch_rule_by_id_query'; const SectionHeader = styled(EuiTitle)` ${() => css` @@ -116,6 +117,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ const { isLoading, indexPatterns } = useFetchIndexPatterns(rules); const [isSubmitting, submitNewExceptionItems] = useAddNewExceptionItems(); const [isClosingAlerts, closeAlerts] = useCloseAlertsFromExceptions(); + const invalidateFetchRuleByIdQuery = useInvalidateFetchRuleByIdQuery(); const allowLargeValueLists = useMemo((): boolean => { if (rules != null && rules.length === 1) { // We'll only block this when we know what rule we're dealing with. @@ -362,6 +364,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ await closeAlerts(ruleStaticIds, addedItems, alertIdToClose, bulkCloseIndex); } + invalidateFetchRuleByIdQuery(); // Rule only would have been updated if we had to create a rule default list // to attach to it, all shared lists would already be referenced on the rule onConfirm(true, closeSingleAlert, bulkCloseAlerts); @@ -387,6 +390,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ onConfirm, bulkCloseIndex, setErrorSubmitting, + invalidateFetchRuleByIdQuery, ]); const isSubmitButtonDisabled = useMemo( diff --git a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts index 0e574c8b19039..bc5d0c894892b 100644 --- a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts +++ b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts @@ -28,6 +28,7 @@ import { } from '../../api'; import { checkIfListCannotBeEdited, isAnExceptionListItem } from '../../utils/list.utils'; import * as i18n from '../../translations'; +import { useInvalidateFetchRuleByIdQuery } from '../../../detection_engine/rule_management/api/hooks/use_fetch_rule_by_id_query'; interface ReferenceModalState { contentText: string; @@ -74,6 +75,7 @@ export const useListDetailsView = () => { ); const [disableManageButton, setDisableManageButton] = useState(true); const [refreshExceptions, setRefreshExceptions] = useState(false); + const invalidateFetchRuleByIdQuery = useInvalidateFetchRuleByIdQuery(); const headerBackOptions: BackOptions = useMemo( () => ({ @@ -310,7 +312,8 @@ export const useListDetailsView = () => { setRefreshExceptions(true); resetManageRulesAfterSaving(); }) - .then(() => setRefreshExceptions(false)); + .then(() => setRefreshExceptions(false)) + .then(() => invalidateFetchRuleByIdQuery()); } catch (err) { handleErrorStatus(err); } @@ -321,6 +324,7 @@ export const useListDetailsView = () => { exceptionListId, resetManageRulesAfterSaving, handleErrorStatus, + invalidateFetchRuleByIdQuery, ]); const onCancelManageRules = useCallback(() => { setShowManageRulesFlyout(false); From 481de7a8ea73e7300b9bf891697343fd8f2f9b69 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Tue, 6 Dec 2022 11:05:32 +0100 Subject: [PATCH 40/40] [Lens][Inspector] Show annotations queries as "Annotations" in the inspector panel (#147026) ## Summary Fixes #141199 Extends the `fetch$` method in the `handleRequest` to accept a custom title+description params to be used on the inspector request log method. In case params are not passed the old behaviour is kept as fallback. The annotation expression can now pass the request meta information about the Annotation request type, that will show up in the panel: Screenshot 2022-12-05 at 18 40 14 ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../esaggs/request_handler.test.ts | 20 +++++++++++++++++ .../expressions/esaggs/request_handler.ts | 22 +++++++++++++------ .../request_event_annotations.ts | 14 ++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts index e0fbb10c05e3f..e0555fbd24076 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts @@ -143,6 +143,26 @@ describe('esaggs expression function - public', () => { }); }); + test('calls searchSource.fetch with custom inspector params', async () => { + await handleRequest({ + ...mockParams, + title: 'MyTitle', + description: 'MyDescription', + }).toPromise(); + const searchSource = await mockParams.searchSourceService.create(); + + expect(searchSource.fetch$).toHaveBeenCalledWith({ + abortSignal: mockParams.abortSignal, + sessionId: mockParams.searchSessionId, + inspector: { + title: 'MyTitle', + description: 'MyDescription', + adapter: undefined, + }, + disableShardFailureWarning: false, + }); + }); + test('tabifies response data', async () => { await handleRequest(mockParams).toPromise(); expect(tabifyAggResponse).toHaveBeenCalledWith( diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index 03512bcd2e270..1497dd9aa1a37 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -33,6 +33,8 @@ export interface RequestHandlerParams { disableShardWarnings?: boolean; getNow?: () => Date; executionContext?: KibanaExecutionContext; + title?: string; + description?: string; } export const handleRequest = ({ @@ -49,6 +51,8 @@ export const handleRequest = ({ disableShardWarnings, getNow, executionContext, + title, + description, }: RequestHandlerParams) => { return defer(async () => { const forceNow = getNow?.(); @@ -117,13 +121,17 @@ export const handleRequest = ({ sessionId: searchSessionId, inspector: { adapter: inspectorAdapters.requests, - title: i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { - defaultMessage: 'Data', - }), - description: i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { - defaultMessage: - 'This request queries Elasticsearch to fetch the data for the visualization.', - }), + title: + title ?? + i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { + defaultMessage: 'Data', + }), + description: + description ?? + i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', + }), }, executionContext, }) diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts index dbf653ea72f3a..56748495a3456 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts @@ -23,6 +23,7 @@ import { ESCalendarInterval, ESFixedInterval, roundDateToESInterval } from '@ela import { Adapters } from '@kbn/inspector-plugin/common'; import { SerializableRecord } from '@kbn/utility-types'; import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { i18n } from '@kbn/i18n'; import { handleRequest } from './handle_request'; import { ANNOTATIONS_PER_BUCKET, @@ -134,6 +135,19 @@ export const requestEventAnnotations = ( searchSourceService: searchSource, getNow, executionContext: getExecutionContext(), + title: i18n.translate( + 'eventAnnotation.fetchEventAnnotations.inspector.dataRequest.title', + { + defaultMessage: 'Annotations', + } + ), + description: i18n.translate( + 'eventAnnotation.fetchEventAnnotations.inspector.dataRequest.description', + { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the annotations.', + } + ), }) );