Skip to content

Commit

Permalink
[Portable Dashboards] Implementation Feature Branch (#144332)
Browse files Browse the repository at this point in the history
This PR makes Dashboards **Portable**. Instead of being tightly coupled to the Dashboard App, the Dashboard Container can now be used in any plugin via the **Dashboard Container Renderer** component. The Dashboard Container renderer is one of the first examples of **Experience Building Blocks** in Kibana.
  • Loading branch information
ThomThomson authored Dec 15, 2022
1 parent 9273d2d commit f3af8e0
Show file tree
Hide file tree
Showing 236 changed files with 5,715 additions and 7,046 deletions.
28 changes: 8 additions & 20 deletions examples/dashboard_embeddable_examples/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import {
EuiPageContentBody_Deprecated as EuiPageContentBody,
EuiPageSideBar_Deprecated as EuiPageSideBar,
EuiSideNav,
EuiTitle,
EuiText,
} from '@elastic/eui';
import 'brace/mode/json';
import { AppMountParameters, IUiSettingsClient } from '@kbn/core/public';
import { DashboardStart } from '@kbn/dashboard-plugin/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { DashboardEmbeddableByValue } from './by_value/embeddable';

interface PageDef {
title: string;
Expand Down Expand Up @@ -56,32 +56,20 @@ const Nav = withRouter(({ history, pages }: NavProps) => {

interface Props {
basename: string;
DashboardContainerByValueRenderer: ReturnType<
DashboardStart['getDashboardContainerByValueRenderer']
>;
uiSettings: IUiSettingsClient;
}

const DashboardEmbeddableExplorerApp = ({
basename,
DashboardContainerByValueRenderer,
uiSettings,
}: Props) => {
const DashboardEmbeddableExplorerApp = ({ basename, uiSettings }: Props) => {
const pages: PageDef[] = [
{
title: 'By value dashboard embeddable',
id: 'dashboardEmbeddableByValue',
title: 'Portable Dashboard basic embeddable example',
id: 'portableDashboardEmbeddableBasicExample',
component: (
<DashboardEmbeddableByValue
DashboardContainerByValueRenderer={DashboardContainerByValueRenderer}
/>
<EuiTitle>
<EuiText>Portable Dashboard embeddable examples coming soon!</EuiText>
</EuiTitle>
),
},
{
title: 'By ref dashboard embeddable',
id: 'dashboardEmbeddableByRef',
component: <div>TODO: Not implemented, but coming soon...</div>,
},
];

const routes = pages.map((page, i) => (
Expand Down
112 changes: 0 additions & 112 deletions examples/dashboard_embeddable_examples/public/by_value/embeddable.tsx

This file was deleted.

This file was deleted.

2 changes: 0 additions & 2 deletions examples/dashboard_embeddable_examples/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ export class DashboardEmbeddableExamples implements Plugin<void, void, {}, Start
return renderApp(
{
basename: params.appBasePath,
DashboardContainerByValueRenderer:
depsStart.dashboard.getDashboardContainerByValueRenderer(),
uiSettings: coreStart.uiSettings,
},
params.element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import {

import { FormattedMessage } from '@kbn/i18n-react';
import { Markdown } from '@kbn/kibana-react-plugin/public';
import { useReduxContainerContext } from '@kbn/presentation-util-plugin/public';
import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public';
import { ControlGroupReduxState } from '../types';
import { pluginServices } from '../../services';
import { EditControlButton } from '../editor/edit_control';
import { ControlGroupStrings } from '../control_group_strings';
import { useChildEmbeddable } from '../../hooks/use_child_embeddable';
import { TIME_SLIDER_CONTROL } from '../../../common';
import { controlGroupReducers } from '../state/control_group_reducers';
import { ControlGroupContainer } from '..';

interface ControlFrameErrorProps {
error: Error;
Expand Down Expand Up @@ -85,10 +87,12 @@ export const ControlFrame = ({
const embeddableRoot: React.RefObject<HTMLDivElement> = useMemo(() => React.createRef(), []);
const [fatalError, setFatalError] = useState<Error>();

const {
useEmbeddableSelector: select,
containerActions: { untilEmbeddableLoaded, removeEmbeddable },
} = useReduxContainerContext<ControlGroupReduxState>();
const { useEmbeddableSelector: select, embeddableInstance: controlGroup } =
useReduxEmbeddableContext<
ControlGroupReduxState,
typeof controlGroupReducers,
ControlGroupContainer
>();

const controlStyle = select((state) => state.explicitInput.controlStyle);

Expand All @@ -97,7 +101,11 @@ export const ControlFrame = ({
overlays: { openConfirm },
} = pluginServices.getServices();

const embeddable = useChildEmbeddable({ untilEmbeddableLoaded, embeddableId, embeddableType });
const embeddable = useChildEmbeddable({
untilEmbeddableLoaded: controlGroup.untilEmbeddableLoaded.bind(controlGroup),
embeddableType,
embeddableId,
});

const [title, setTitle] = useState<string>();

Expand Down Expand Up @@ -143,7 +151,7 @@ export const ControlFrame = ({
buttonColor: 'danger',
}).then((confirmed) => {
if (confirmed) {
removeEmbeddable(embeddableId);
controlGroup.removeEmbeddable(embeddableId);
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@ import {
} from '@dnd-kit/core';

import { ViewMode } from '@kbn/embeddable-plugin/public';
import { useReduxContainerContext } from '@kbn/presentation-util-plugin/public';
import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public';

import { ControlGroupReduxState } from '../types';
import { controlGroupReducers } from '../state/control_group_reducers';
import { ControlClone, SortableControl } from './control_group_sortable_item';

export const ControlGroup = () => {
// Redux embeddable container Context
const reduxContainerContext = useReduxContainerContext<
const reduxContext = useReduxEmbeddableContext<
ControlGroupReduxState,
typeof controlGroupReducers
>();
const {
actions: { setControlOrders },
useEmbeddableSelector: select,
useEmbeddableDispatch,
} = reduxContainerContext;
} = reduxContext;
const dispatch = useEmbeddableDispatch();

// current state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import classNames from 'classnames';

import { useReduxContainerContext } from '@kbn/presentation-util-plugin/public';
import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public';
import { ControlFrame, ControlFrameProps } from './control_frame_component';
import { ControlGroupReduxState } from '../types';
import { ControlGroupStrings } from '../control_group_strings';
Expand Down Expand Up @@ -67,7 +67,7 @@ const SortableControlInner = forwardRef<
dragHandleRef
) => {
const { isOver, isDragging, draggingIndex, index } = dragInfo;
const { useEmbeddableSelector } = useReduxContainerContext<ControlGroupReduxState>();
const { useEmbeddableSelector } = useReduxEmbeddableContext<ControlGroupReduxState>();
const panels = useEmbeddableSelector((state) => state.explicitInput.panels);

const grow = panels[embeddableId].grow;
Expand Down Expand Up @@ -119,7 +119,7 @@ const SortableControlInner = forwardRef<
* can be quite cumbersome.
*/
export const ControlClone = ({ draggingId }: { draggingId: string }) => {
const { useEmbeddableSelector: select } = useReduxContainerContext<ControlGroupReduxState>();
const { useEmbeddableSelector: select } = useReduxEmbeddableContext<ControlGroupReduxState>();
const panels = select((state) => state.explicitInput.panels);
const controlStyle = select((state) => state.explicitInput.controlStyle);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import useLifecycles from 'react-use/lib/useLifecycles';
import React, { useMemo, useRef, useState } from 'react';

import { IEmbeddable } from '@kbn/embeddable-plugin/public';
import { useReduxContainerContext } from '@kbn/presentation-util-plugin/public';
import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public';

import { pluginServices } from '../services';
import { getDefaultControlGroupInput } from '../../common';
Expand Down Expand Up @@ -78,7 +78,7 @@ export const ControlGroupRenderer = ({
};

export const useControlGroupContainerContext = () =>
useReduxContainerContext<ControlGroupReduxState, typeof controlGroupReducers>();
useReduxEmbeddableContext<ControlGroupReduxState, typeof controlGroupReducers>();

// required for dynamic import using React.lazy()
// eslint-disable-next-line import/no-default-export
Expand Down
Loading

0 comments on commit f3af8e0

Please sign in to comment.