{
display: flex;
justify-content: end;
align-items: center;
- padding: ${euiTheme.size.s};
+ padding: 0 ${euiTheme.size.s};
+ height: var(--kbnProjectHeaderAppActionMenuHeight, ${euiTheme.size.xxxl});
margin-bottom: -${euiTheme.border.width.thin};
/* fixates the elements position in the viewport, removes the element from the flow of the page */
position: sticky;
diff --git a/packages/kbn-apm-synthtrace/index.ts b/packages/kbn-apm-synthtrace/index.ts
index abcf201bf96c2..921243e67ac6a 100644
--- a/packages/kbn-apm-synthtrace/index.ts
+++ b/packages/kbn-apm-synthtrace/index.ts
@@ -16,3 +16,8 @@ export { InfraSynthtraceEsClient } from './src/lib/infra/infra_synthtrace_es_cli
export { AssetsSynthtraceEsClient } from './src/lib/assets/assets_synthtrace_es_client';
export { MonitoringSynthtraceEsClient } from './src/lib/monitoring/monitoring_synthtrace_es_client';
+
+export {
+ addObserverVersionTransform,
+ deleteSummaryFieldTransform,
+} from './src/lib/utils/transform_helpers';
diff --git a/packages/kbn-apm-synthtrace/src/lib/shared/base_client.ts b/packages/kbn-apm-synthtrace/src/lib/shared/base_client.ts
index 4a3a79e2b78d9..4b00a574b447e 100644
--- a/packages/kbn-apm-synthtrace/src/lib/shared/base_client.ts
+++ b/packages/kbn-apm-synthtrace/src/lib/shared/base_client.ts
@@ -13,7 +13,7 @@ import {
SynthtraceESAction,
SynthtraceGenerator,
} from '@kbn/apm-synthtrace-client';
-import { castArray } from 'lodash';
+import { castArray, isFunction } from 'lodash';
import { Readable, Transform } from 'stream';
import { isGeneratorObject } from 'util/types';
import { Logger } from '../utils/create_logger';
@@ -69,9 +69,17 @@ export class SynthtraceEsClient {
this.pipelineCallback = cb;
}
- async index(streamOrGenerator: MaybeArray>) {
+ async index(
+ streamOrGenerator: MaybeArray>,
+ pipelineCallback?: (base: Readable) => NodeJS.WritableStream
+ ) {
this.logger.debug(`Bulk indexing ${castArray(streamOrGenerator).length} stream(s)`);
+ const previousPipelineCallback = this.pipelineCallback;
+ if (isFunction(pipelineCallback)) {
+ this.pipeline(pipelineCallback);
+ }
+
const allStreams = castArray(streamOrGenerator).map((obj) => {
const base = isGeneratorObject(obj) ? Readable.from(obj) : obj;
@@ -121,6 +129,11 @@ export class SynthtraceEsClient {
this.logger.info(`Produced ${count} events`);
+ // restore pipeline callback
+ if (pipelineCallback) {
+ this.pipeline(previousPipelineCallback);
+ }
+
if (this.refreshAfterIndex) {
await this.refresh();
}
diff --git a/packages/kbn-apm-synthtrace/src/lib/utils/transform_helpers.ts b/packages/kbn-apm-synthtrace/src/lib/utils/transform_helpers.ts
new file mode 100644
index 0000000000000..abd841bc9a837
--- /dev/null
+++ b/packages/kbn-apm-synthtrace/src/lib/utils/transform_helpers.ts
@@ -0,0 +1,33 @@
+/*
+ * 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 { Transform } from 'stream';
+
+export function addObserverVersionTransform(observerVersion: string) {
+ return new Transform({
+ objectMode: true,
+ transform(chunk: { observer?: { version?: string } }, encoding, callback) {
+ if (chunk?.observer?.version) {
+ chunk.observer.version = observerVersion;
+ }
+ callback(null, chunk);
+ },
+ });
+}
+
+export function deleteSummaryFieldTransform() {
+ return new Transform({
+ objectMode: true,
+ transform(chunk: { transaction?: { duration?: { summary?: number } } }, encoding, callback) {
+ if (chunk?.transaction?.duration?.summary) {
+ delete chunk.transaction.duration.summary;
+ }
+ callback(null, chunk);
+ },
+ });
+}
diff --git a/packages/kbn-content-management-utils/src/saved_object_content_storage.ts b/packages/kbn-content-management-utils/src/saved_object_content_storage.ts
index 8ff22a0d9be02..070bb9cd5d739 100644
--- a/packages/kbn-content-management-utils/src/saved_object_content_storage.ts
+++ b/packages/kbn-content-management-utils/src/saved_object_content_storage.ts
@@ -129,7 +129,7 @@ export type UpdateArgsToSoUpdateOptions = (
params: Types['UpdateOptions']
) => SavedObjectsUpdateOptions;
-export interface SOContentStorageConstrutorParams {
+export interface SOContentStorageConstructorParams {
savedObjectType: string;
cmServicesDefinition: ServicesDefinitionSet;
// this is necessary since unexpected saved object attributes could cause schema validation to fail
@@ -137,6 +137,12 @@ export interface SOContentStorageConstrutorParams {
createArgsToSoCreateOptions?: CreateArgsToSoCreateOptions;
updateArgsToSoUpdateOptions?: UpdateArgsToSoUpdateOptions;
searchArgsToSOFindOptions?: SearchArgsToSOFindOptions;
+ /**
+ * MSearch is a feature that allows searching across multiple content types
+ * (for example, could be used in a general content finder or the like)
+ *
+ * defaults to false
+ */
enableMSearch?: boolean;
mSearchAdditionalSearchFields?: string[];
@@ -163,7 +169,7 @@ export abstract class SOContentStorage
mSearchAdditionalSearchFields,
logger,
throwOnResultValidationError,
- }: SOContentStorageConstrutorParams) {
+ }: SOContentStorageConstructorParams) {
this.logger = logger;
this.throwOnResultValidationError = throwOnResultValidationError ?? false;
this.savedObjectType = savedObjectType;
@@ -219,8 +225,8 @@ export abstract class SOContentStorage
private throwOnResultValidationError: boolean;
private logger: Logger;
- private savedObjectType: SOContentStorageConstrutorParams['savedObjectType'];
- private cmServicesDefinition: SOContentStorageConstrutorParams['cmServicesDefinition'];
+ private savedObjectType: SOContentStorageConstructorParams['savedObjectType'];
+ private cmServicesDefinition: SOContentStorageConstructorParams['cmServicesDefinition'];
private createArgsToSoCreateOptions: CreateArgsToSoCreateOptions;
private updateArgsToSoUpdateOptions: UpdateArgsToSoUpdateOptions;
private searchArgsToSOFindOptions: SearchArgsToSOFindOptions;
diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts
index c389fe02f06d8..6f2800a8d6348 100644
--- a/packages/kbn-doc-links/src/get_doc_links.ts
+++ b/packages/kbn-doc-links/src/get_doc_links.ts
@@ -856,7 +856,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
featureRoles: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/synthetics-feature-roles.html`,
},
esql: {
- statsBy: `${ELASTICSEARCH_DOCS}esql-stats-by.html`,
+ statsBy: `${ELASTICSEARCH_DOCS}esql.html`,
},
telemetry: {
settings: `${KIBANA_DOCS}telemetry-settings-kbn.html`,
diff --git a/packages/kbn-expandable-flyout/.storybook/main.js b/packages/kbn-expandable-flyout/.storybook/main.js
new file mode 100644
index 0000000000000..8dc3c5d1518f4
--- /dev/null
+++ b/packages/kbn-expandable-flyout/.storybook/main.js
@@ -0,0 +1,9 @@
+/*
+ * 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.
+ */
+
+module.exports = require('@kbn/storybook').defaultConfig;
diff --git a/packages/kbn-expandable-flyout/README.md b/packages/kbn-expandable-flyout/README.md
index 8a9a201ff89af..63a6f9483ead0 100644
--- a/packages/kbn-expandable-flyout/README.md
+++ b/packages/kbn-expandable-flyout/README.md
@@ -9,30 +9,36 @@ The flyout is composed of 3 sections:
- a left wider section to show more details
- a preview section, that overlays the right section. This preview section can display multiple panels one after the other and displays a `Back` button
-At the moment, displaying more than one flyout within the same plugin might be complicated, unless there are in difference areas in the codebase and the contexts don't conflict with each other.
+> Run `yarn storybook expandable_flyout` to take a quick look at the expandable flyout in action
-## What the package offers
+## Design decisions
-The ExpandableFlyout [React component](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/index) that renders the UI.
+The expandable-flyout package is designed to render a single flyout for an entire plugin. While displaying multiple flyouts might be feasible, it will be a bit complicated, and we recommend instead to build multiple panels, with each their own context to manage their data (for example, take a look at the Security Solution [setup](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout)).
-The ExpandableFlyout [React context](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/context) that exposes the following api:
+The expandable-flyout is making some strict UI design decisions:
+- when in collapsed mode (i.e. when only the right/preview section is open), the flyout's width is fixed to the EUI `s` size
+- when in expanded mode (i.e. when the left section is opened), the flyout's width is fixed to the EUI `l` size. Internally the right, left and preview sections' widths are set to a hardcoded percentage (40%, 60$ and 40% respectively)
+
+## Package API
+
+The ExpandableFlyout [React component](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/index.tsx) renders the UI, leveraging an [EuiFlyout](https://eui.elastic.co/#/layout/flyout).
+
+The ExpandableFlyout [React context](https://github.com/elastic/kibana/blob/main/packages/kbn-expandable-flyout/src/context.tsx) manages the internal state of the expandable flyout, and exposes the following api:
- **openFlyout**: open the flyout with a set of panels
-- **openFlyoutRightPanel**: open a right panel
-- **openFlyoutLeftPanel**: open a left panel
-- **openFlyoutPreviewPanel**: open a preview panel
-- **closeFlyoutRightPanel**: close the right panel
-- **closeFlyoutLeftPanel**: close the left panel
-- **closeFlyoutPreviewPanel**: close the preview panels
-- **previousFlyoutPreviewPanel**: navigate to the previous preview panel
+- **openRightPanel**: open a right panel
+- **openLeftPanel**: open a left panel
+- **openPreviewPanel**: open a preview panel
+- **closeRightPanel**: close the right panel
+- **closeLeftPanel**: close the left panel
+- **closePreviewPanel**: close the preview panels
+- **previousPreviewPanel**: navigate to the previous preview panel
- **closeFlyout**: close the flyout
-To retrieve the flyout's layout (left, right and preview panels), you can use the **panels** from the same [React context](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/context);
-
-- To have more details about how these above api work, see the code documentation [here](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/utils/helpers).
+To retrieve the flyout's layout (left, right and preview panels), you can use the **panels** from the same [React context](https://github.com/elastic/kibana/blob/main/packages/kbn-expandable-flyout/src/context.tsx).
## Usage
-To use the expandable flyout in your plugin, first you need wrap your code with the context provider at a high enough level as follows:
+To use the expandable flyout in your plugin, first you need wrap your code with the [context provider](https://github.com/elastic/kibana/blob/main/packages/kbn-expandable-flyout/src/context.tsx) at a high enough level as follows:
```typescript jsx
@@ -41,25 +47,20 @@ To use the expandable flyout in your plugin, first you need wrap your code with
```
-Then use the React UI component where you need:
+Then use the [React UI component](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/index.tsx) where you need:
```typescript jsx
```
-where `myPanels` is a list of all the panels that can be rendered in the flyout (see interface [here](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/index)).
+_where `myPanels` is a list of all the panels that can be rendered in the flyout_
## Terminology
### Section
-One of the 3 areas of the flyout (left, right or preview).
+One of the 3 areas of the flyout (**left**, **right** or **preview**).
### Panel
-A set of properties defining what's displayed in one of the flyout section.
-
-## Future work
-
-- add the feature to save the flyout state (layout) to the url (https://github.com/elastic/security-team/issues/6119)
-- introduce the notion of scope to be able to handle more than one flyout per plugin??
\ No newline at end of file
+A set of properties defining what's displayed in one of the flyout section (see interface [here](https://github.com/elastic/kibana/blob/main/packages/kbn-expandable-flyout/src/types.ts)).
diff --git a/packages/kbn-expandable-flyout/src/components/left_section.tsx b/packages/kbn-expandable-flyout/src/components/left_section.tsx
index d388923c01d69..1d2a4a7eeabac 100644
--- a/packages/kbn-expandable-flyout/src/components/left_section.tsx
+++ b/packages/kbn-expandable-flyout/src/components/left_section.tsx
@@ -8,7 +8,7 @@
import { EuiFlexItem } from '@elastic/eui';
import React, { useMemo } from 'react';
-import { LEFT_SECTION } from './test_ids';
+import { LEFT_SECTION_TEST_ID } from './test_ids';
interface LeftSectionProps {
/**
@@ -30,7 +30,7 @@ export const LeftSection: React.FC = ({ component, width }: Le
[width]
);
return (
-
+
{component}
);
diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx
index 41926400e11f5..f365c8f299623 100644
--- a/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx
+++ b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx
@@ -9,7 +9,10 @@
import React from 'react';
import { render } from '@testing-library/react';
import { PreviewSection } from './preview_section';
-import { PREVIEW_SECTION_BACK_BUTTON, PREVIEW_SECTION_CLOSE_BUTTON } from './test_ids';
+import {
+ PREVIEW_SECTION_BACK_BUTTON_TEST_ID,
+ PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID,
+} from './test_ids';
import { ExpandableFlyoutContext } from '../context';
describe('PreviewSection', () => {
@@ -36,7 +39,7 @@ describe('PreviewSection', () => {
);
- expect(getByTestId(PREVIEW_SECTION_CLOSE_BUTTON)).toBeInTheDocument();
+ expect(getByTestId(PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID)).toBeInTheDocument();
});
it('should render back button in header', () => {
@@ -50,6 +53,6 @@ describe('PreviewSection', () => {
);
- expect(getByTestId(PREVIEW_SECTION_BACK_BUTTON)).toBeInTheDocument();
+ expect(getByTestId(PREVIEW_SECTION_BACK_BUTTON_TEST_ID)).toBeInTheDocument();
});
});
diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.tsx
index 1bb3f84d1b5f5..1cc2243d65849 100644
--- a/packages/kbn-expandable-flyout/src/components/preview_section.tsx
+++ b/packages/kbn-expandable-flyout/src/components/preview_section.tsx
@@ -19,10 +19,10 @@ import React from 'react';
import { css } from '@emotion/react';
import { has } from 'lodash';
import {
- PREVIEW_SECTION_BACK_BUTTON,
- PREVIEW_SECTION_CLOSE_BUTTON,
- PREVIEW_SECTION_HEADER,
- PREVIEW_SECTION,
+ PREVIEW_SECTION_BACK_BUTTON_TEST_ID,
+ PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID,
+ PREVIEW_SECTION_HEADER_TEST_ID,
+ PREVIEW_SECTION_TEST_ID,
} from './test_ids';
import { useExpandableFlyoutContext } from '../..';
import { BACK_BUTTON, CLOSE_BUTTON } from './translations';
@@ -97,7 +97,7 @@ export const PreviewSection: React.FC = ({
closePreviewPanel()}
- data-test-subj={PREVIEW_SECTION_CLOSE_BUTTON}
+ data-test-subj={PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID}
aria-label={CLOSE_BUTTON}
/>
@@ -110,7 +110,7 @@ export const PreviewSection: React.FC = ({
iconType="arrowLeft"
iconSide="left"
onClick={() => previousPreviewPanel()}
- data-test-subj={PREVIEW_SECTION_BACK_BUTTON}
+ data-test-subj={PREVIEW_SECTION_BACK_BUTTON_TEST_ID}
aria-label={BACK_BUTTON}
>
{BACK_BUTTON}
@@ -140,7 +140,7 @@ export const PreviewSection: React.FC = ({
box-shadow: 0px 0px 5px 5px ${euiTheme.colors.darkShade};
`}
className="eui-yScroll"
- data-test-subj={PREVIEW_SECTION}
+ data-test-subj={PREVIEW_SECTION_TEST_ID}
>
{isPreviewBanner(banner) && (
@@ -149,7 +149,11 @@ export const PreviewSection: React.FC = ({
)}
-
+
{header}
{component}
diff --git a/packages/kbn-expandable-flyout/src/components/right_section.tsx b/packages/kbn-expandable-flyout/src/components/right_section.tsx
index 7857c2b4fba48..6e7e94dc14048 100644
--- a/packages/kbn-expandable-flyout/src/components/right_section.tsx
+++ b/packages/kbn-expandable-flyout/src/components/right_section.tsx
@@ -8,7 +8,7 @@
import { EuiFlexItem } from '@elastic/eui';
import React, { useMemo } from 'react';
-import { RIGHT_SECTION } from './test_ids';
+import { RIGHT_SECTION_TEST_ID } from './test_ids';
interface RightSectionProps {
/**
@@ -34,7 +34,7 @@ export const RightSection: React.FC = ({
);
return (
-
+
{component}
);
diff --git a/packages/kbn-expandable-flyout/src/components/test_ids.ts b/packages/kbn-expandable-flyout/src/components/test_ids.ts
index 430f87f85c5d5..439ba2e826073 100644
--- a/packages/kbn-expandable-flyout/src/components/test_ids.ts
+++ b/packages/kbn-expandable-flyout/src/components/test_ids.ts
@@ -6,14 +6,14 @@
* Side Public License, v 1.
*/
-export const RIGHT_SECTION = 'rightSection';
+export const RIGHT_SECTION_TEST_ID = 'rightSection';
-export const LEFT_SECTION = 'leftSection';
+export const LEFT_SECTION_TEST_ID = 'leftSection';
-export const PREVIEW_SECTION = 'previewSection';
+export const PREVIEW_SECTION_TEST_ID = 'previewSection';
-export const PREVIEW_SECTION_CLOSE_BUTTON = 'previewSectionCloseButton';
+export const PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID = 'previewSectionCloseButton';
-export const PREVIEW_SECTION_BACK_BUTTON = 'previewSectionBackButton';
+export const PREVIEW_SECTION_BACK_BUTTON_TEST_ID = 'previewSectionBackButton';
-export const PREVIEW_SECTION_HEADER = 'previewSectionHeader';
+export const PREVIEW_SECTION_HEADER_TEST_ID = 'previewSectionHeader';
diff --git a/packages/kbn-expandable-flyout/src/index.stories.tsx b/packages/kbn-expandable-flyout/src/index.stories.tsx
new file mode 100644
index 0000000000000..2bbc26c3363f3
--- /dev/null
+++ b/packages/kbn-expandable-flyout/src/index.stories.tsx
@@ -0,0 +1,196 @@
+/*
+ * 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 type { Story } from '@storybook/react';
+import {
+ EuiButton,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFlyoutBody,
+ EuiFlyoutFooter,
+ EuiFlyoutHeader,
+ EuiPanel,
+ EuiTitle,
+} from '@elastic/eui';
+import { ExpandableFlyout } from '.';
+import { ExpandableFlyoutContext } from './context';
+
+export default {
+ component: ExpandableFlyout,
+ title: 'ExpandableFlyout',
+};
+
+const registeredPanels = [
+ {
+ key: 'right',
+ component: () => (
+ <>
+
+
+