Skip to content

Commit

Permalink
Merge branch 'main' into alerting/alert-delay-actual-fe
Browse files Browse the repository at this point in the history
  • Loading branch information
doakalexi authored Feb 13, 2024
2 parents 7faa680 + b1389a3 commit 4e0758e
Show file tree
Hide file tree
Showing 206 changed files with 10,107 additions and 2,574 deletions.
9 changes: 6 additions & 3 deletions examples/embeddable_examples/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
"server": true,
"browser": true,
"requiredPlugins": [
"dataViews",
"embeddable",
"uiActions",
"dashboard",
"data",
"charts",
"fieldFormats"
],
"extraPublicDirs": [
"public/hello_world"
]
"requiredBundles": ["presentationUtil"],
"extraPublicDirs": ["public/hello_world"]
}
}
20 changes: 17 additions & 3 deletions examples/embeddable_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
* Side Public License, v 1.
*/

import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public';
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import {
HelloWorldEmbeddableFactory,
HELLO_WORLD_EMBEDDABLE,
Expand All @@ -33,14 +37,21 @@ import {
} from './filter_debugger';
import { registerMarkdownEditorEmbeddable } from './react_embeddables/eui_markdown/eui_markdown_react_embeddable';
import { registerCreateEuiMarkdownAction } from './react_embeddables/eui_markdown/create_eui_markdown_action';
import { registerFieldListFactory } from './react_embeddables/field_list/field_list_react_embeddable';
import { registerCreateFieldListAction } from './react_embeddables/field_list/create_field_list_action';

export interface EmbeddableExamplesSetupDependencies {
embeddable: EmbeddableSetup;
uiActions: UiActionsStart;
}

export interface EmbeddableExamplesStartDependencies {
dataViews: DataViewsPublicPluginStart;
embeddable: EmbeddableStart;
uiActions: UiActionsStart;
data: DataPublicPluginStart;
charts: ChartsPluginStart;
fieldFormats: FieldFormatsStart;
}

interface ExampleEmbeddableFactories {
Expand Down Expand Up @@ -70,9 +81,6 @@ export class EmbeddableExamplesPlugin
core: CoreSetup<EmbeddableExamplesStartDependencies>,
deps: EmbeddableExamplesSetupDependencies
) {
registerMarkdownEditorEmbeddable();
registerCreateEuiMarkdownAction(deps.uiActions);

this.exampleEmbeddableFactories.getHelloWorldEmbeddableFactory =
deps.embeddable.registerEmbeddableFactory(
HELLO_WORLD_EMBEDDABLE,
Expand Down Expand Up @@ -104,6 +112,12 @@ export class EmbeddableExamplesPlugin
core: CoreStart,
deps: EmbeddableExamplesStartDependencies
): EmbeddableExamplesStart {
registerFieldListFactory(core, deps);
registerCreateFieldListAction(deps.uiActions);

registerMarkdownEditorEmbeddable();
registerCreateEuiMarkdownAction(deps.uiActions);

return {
createSampleData: async () => {},
factories: this.exampleEmbeddableFactories as ExampleEmbeddableFactories,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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.
*/

export const FIELD_LIST_ID = 'field_list';
export const ADD_FIELD_LIST_ACTION_ID = 'create_field_list';
export const FIELD_LIST_DATA_VIEW_REF_NAME = 'field_list_data_view_id';
Original file line number Diff line number Diff line change
@@ -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 { i18n } from '@kbn/i18n';
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin';
import { ADD_FIELD_LIST_ACTION_ID, FIELD_LIST_ID } from './constants';

export const registerCreateFieldListAction = (uiActions: UiActionsPublicStart) => {
uiActions.registerAction<EmbeddableApiContext>({
id: ADD_FIELD_LIST_ACTION_ID,
getIconType: () => 'indexOpen',
isCompatible: async ({ embeddable }) => {
return apiIsPresentationContainer(embeddable);
},
execute: async ({ embeddable }) => {
if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError();
embeddable.addNewPanel({
panelType: FIELD_LIST_ID,
});
},
getDisplayName: () =>
i18n.translate('embeddableExamples.unifiedFieldList.displayName', {
defaultMessage: 'Field list',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_FIELD_LIST_ACTION_ID);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* 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 } from '@elastic/eui';
import { css } from '@emotion/react';
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import { Reference } from '@kbn/content-management-utils';
import { CoreStart } from '@kbn/core-lifecycle-browser';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import {
DataViewsPublicPluginStart,
DATA_VIEW_SAVED_OBJECT_TYPE,
type DataView,
} from '@kbn/data-views-plugin/public';
import {
initializeReactEmbeddableTitles,
initializeReactEmbeddableUuid,
ReactEmbeddableFactory,
RegisterReactEmbeddable,
registerReactEmbeddableFactory,
useReactEmbeddableApiHandle,
useReactEmbeddableUnsavedChanges,
} from '@kbn/embeddable-plugin/public';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { i18n } from '@kbn/i18n';
import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
import { LazyDataViewPicker, withSuspense } from '@kbn/presentation-util-plugin/public';
import { euiThemeVars } from '@kbn/ui-theme';
import {
UnifiedFieldListSidebarContainer,
type UnifiedFieldListSidebarContainerProps,
} from '@kbn/unified-field-list';
import { cloneDeep } from 'lodash';
import React, { useEffect, useState } from 'react';
import { BehaviorSubject } from 'rxjs';
import { FIELD_LIST_DATA_VIEW_REF_NAME, FIELD_LIST_ID } from './constants';
import { FieldListApi, FieldListSerializedStateState } from './types';

const DataViewPicker = withSuspense(LazyDataViewPicker, null);

const getCreationOptions: UnifiedFieldListSidebarContainerProps['getCreationOptions'] = () => {
return {
originatingApp: '',
localStorageKeyPrefix: 'examples',
timeRangeUpdatesType: 'timefilter',
compressed: true,
showSidebarToggleButton: false,
disablePopularFields: true,
};
};

export const registerFieldListFactory = (
core: CoreStart,
{
dataViews,
data,
charts,
fieldFormats,
}: {
dataViews: DataViewsPublicPluginStart;
data: DataPublicPluginStart;
charts: ChartsPluginStart;
fieldFormats: FieldFormatsStart;
}
) => {
const fieldListEmbeddableFactory: ReactEmbeddableFactory<
FieldListSerializedStateState,
FieldListApi
> = {
deserializeState: (state) => {
const serializedState = cloneDeep(state.rawState) as FieldListSerializedStateState;
// inject the reference
const dataViewIdRef = state.references?.find(
(ref) => ref.name === FIELD_LIST_DATA_VIEW_REF_NAME
);
if (dataViewIdRef && serializedState) {
serializedState.dataViewId = dataViewIdRef?.id;
}
return serializedState;
},
getComponent: async (initialState, maybeId) => {
const uuid = initializeReactEmbeddableUuid(maybeId);
const { titlesApi, titleComparators, serializeTitles } =
initializeReactEmbeddableTitles(initialState);

const allDataViews = await dataViews.getIdsWithTitle();

const selectedDataViewId$ = new BehaviorSubject<string | undefined>(
initialState.dataViewId ?? (await dataViews.getDefaultDataView())?.id
);
const selectedFieldNames$ = new BehaviorSubject<string[] | undefined>(
initialState.selectedFieldNames
);

return RegisterReactEmbeddable((apiRef) => {
const { unsavedChanges, resetUnsavedChanges } = useReactEmbeddableUnsavedChanges(
uuid,
fieldListEmbeddableFactory,
{
dataViewId: [selectedDataViewId$, (value) => selectedDataViewId$.next(value)],
selectedFieldNames: [
selectedFieldNames$,
(value) => selectedFieldNames$.next(value),
(a, b) => {
return (a?.slice().sort().join(',') ?? '') === (b?.slice().sort().join(',') ?? '');
},
],
...titleComparators,
}
);

useReactEmbeddableApiHandle(
{
...titlesApi,
unsavedChanges,
resetUnsavedChanges,
serializeState: async () => {
const dataViewId = selectedDataViewId$.getValue();
const references: Reference[] = dataViewId
? [
{
type: DATA_VIEW_SAVED_OBJECT_TYPE,
name: FIELD_LIST_DATA_VIEW_REF_NAME,
id: dataViewId,
},
]
: [];
return {
rawState: {
...serializeTitles(),
// here we skip serializing the dataViewId, because the reference contains that information.
selectedFieldNames: selectedFieldNames$.getValue(),
},
references,
};
},
},
apiRef,
uuid
);

const [selectedDataViewId, selectedFieldNames] = useBatchedPublishingSubjects(
selectedDataViewId$,
selectedFieldNames$
);

const [selectedDataView, setSelectedDataView] = useState<DataView | undefined>(undefined);

useEffect(() => {
if (!selectedDataViewId) return;
let mounted = true;
(async () => {
const dataView = await dataViews.get(selectedDataViewId);
if (!mounted) return;
setSelectedDataView(dataView);
})();
return () => {
mounted = false;
};
}, [selectedDataViewId]);

return (
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem
grow={false}
css={css`
padding: ${euiThemeVars.euiSizeS};
`}
>
<DataViewPicker
dataViews={allDataViews}
selectedDataViewId={selectedDataViewId}
onChangeDataViewId={(nextSelection) => {
selectedDataViewId$.next(nextSelection);
}}
trigger={{
label:
selectedDataView?.getName() ??
i18n.translate('embeddableExamples.unifiedFieldList.selectDataViewMessage', {
defaultMessage: 'Please select a data view',
}),
}}
/>
</EuiFlexItem>
<EuiFlexItem>
{selectedDataView ? (
<UnifiedFieldListSidebarContainer
fullWidth={true}
variant="list-always"
dataView={selectedDataView}
allFields={selectedDataView.fields}
getCreationOptions={getCreationOptions}
workspaceSelectedFieldNames={selectedFieldNames}
services={{ dataViews, data, fieldFormats, charts, core }}
onAddFieldToWorkspace={(field) =>
selectedFieldNames$.next([
...(selectedFieldNames$.getValue() ?? []),
field.name,
])
}
onRemoveFieldFromWorkspace={(field) => {
selectedFieldNames$.next(
(selectedFieldNames$.getValue() ?? []).filter((name) => name !== field.name)
);
}}
/>
) : null}
</EuiFlexItem>
</EuiFlexGroup>
);
});
},
};

registerReactEmbeddableFactory(FIELD_LIST_ID, fieldListEmbeddableFactory);
};
Original file line number Diff line number Diff line change
@@ -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 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 {
DefaultEmbeddableApi,
SerializedReactEmbeddableTitles,
} from '@kbn/embeddable-plugin/public';

export type FieldListSerializedStateState = SerializedReactEmbeddableTitles & {
dataViewId?: string;
selectedFieldNames?: string[];
};

export type FieldListApi = DefaultEmbeddableApi;
10 changes: 9 additions & 1 deletion examples/embeddable_examples/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
"@kbn/ui-theme",
"@kbn/i18n",
"@kbn/es-query",
"@kbn/presentation-containers"
"@kbn/presentation-containers",
"@kbn/data-views-plugin",
"@kbn/data-plugin",
"@kbn/charts-plugin",
"@kbn/field-formats-plugin",
"@kbn/content-management-utils",
"@kbn/core-lifecycle-browser",
"@kbn/presentation-util-plugin",
"@kbn/unified-field-list"
]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"@dnd-kit/utilities": "^2.0.0",
"@elastic/apm-rum": "^5.16.0",
"@elastic/apm-rum-react": "^2.0.2",
"@elastic/charts": "63.0.0",
"@elastic/charts": "63.1.0",
"@elastic/datemath": "5.0.3",
"@elastic/elasticsearch": "npm:@elastic/[email protected]",
"@elastic/ems-client": "8.5.1",
Expand Down
Loading

0 comments on commit 4e0758e

Please sign in to comment.