Skip to content

Commit

Permalink
Render editor page with basic nav actions
Browse files Browse the repository at this point in the history
Added dashboard embeddable container to render the dashboard editor page.

Signed-off-by: abbyhu2000 <abigailhu2000@gmail.com>
  • Loading branch information
abbyhu2000 committed Jun 1, 2023
1 parent 7142304 commit 526e3d6
Show file tree
Hide file tree
Showing 10 changed files with 660 additions and 267 deletions.
228 changes: 42 additions & 186 deletions src/plugins/dashboard/public/application/components/dashboard_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,24 @@
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { EventEmitter } from 'events';
import { EMPTY, Subscription, merge } from 'rxjs';
import { catchError, distinctUntilChanged, map, mapTo, startWith, switchMap } from 'rxjs/operators';
import deepEqual from 'fast-deep-equal';
import { DashboardTopNav } from '../components/dashboard_top_nav';
import { useChromeVisibility } from '../utils/use/use_chrome_visibility';
import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
import { useSavedDashboardInstance } from '../utils/use/use_saved_dashboard_instance';

import { DashboardServices, SavedDashboardPanel } from '../../types';
import {
DASHBOARD_CONTAINER_TYPE,
DashboardContainer,
DashboardContainerInput,
DashboardPanelState,
} from '../embeddable';
import {
ContainerOutput,
ErrorEmbeddable,
ViewMode,
isErrorEmbeddable,
} from '../../embeddable_plugin';
import { DashboardEmptyScreen, DashboardEmptyScreenProps } from '../dashboard_empty_screen';
import { convertSavedDashboardPanelToPanelState } from '../lib/embeddable_saved_object_converters';
import { DashboardServices } from '../../types';
import { useDashboardAppState } from '../utils/use/use_dashboard_app_state';
import { useDashboardContainer } from '../utils/use/use_dashboard_container';
import { useEditorUpdates } from '../utils/use/use_editor_updates';

export const DashboardEditor = () => {
const { id: dashboardIdFromUrl } = useParams<{ id: string }>();
const { services } = useOpenSearchDashboards<DashboardServices>();
const { embeddable, data, dashboardConfig, embeddableCapabilities, uiSettings, http } = services;
const { query: queryService } = data;
const { visualizeCapabilities, mapsCapabilities } = embeddableCapabilities;
const timefilter = queryService.timefilter.timefilter;
const isChromeVisible = useChromeVisibility(services.chrome);
const [eventEmitter] = useState(new EventEmitter());
const dashboardDom = document.getElementById('dashboardViewport');

Check warning on line 24 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L20-L24

Added lines #L20 - L24 were not covered by tests

const { savedDashboardInstance } = useSavedDashboardInstance(
const savedDashboardInstance = useSavedDashboardInstance(

Check warning on line 26 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L26

Added line #L26 was not covered by tests
services,
eventEmitter,
isChromeVisible,
Expand All @@ -50,176 +32,50 @@ export const DashboardEditor = () => {

const { appState } = useDashboardAppState(services, eventEmitter, savedDashboardInstance);

Check warning on line 33 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L33

Added line #L33 was not covered by tests

const appStateData = appState?.get();
if (!appStateData) {
return null;
}
// let dashboardContainer: DashboardContainer | undefined;
let inputSubscription: Subscription | undefined;
let outputSubscription: Subscription | undefined;

const [dashboardContainer, setDashboardContainer] = useState<DashboardContainer>({});
const dashboardDom = document.getElementById('dashboardViewport');
const dashboardFactory = embeddable.getEmbeddableFactory<
DashboardContainerInput,
ContainerOutput,
DashboardContainer
>(DASHBOARD_CONTAINER_TYPE);

const getShouldShowEditHelp = () => {
return (
!appStateData.panels.length &&
appStateData.viewMode === ViewMode.EDIT &&
!dashboardConfig.getHideWriteControls()
);
};

const getShouldShowViewHelp = () => {
return (
!appStateData.panels.length &&
appStateData.viewMode === ViewMode.VIEW &&
!dashboardConfig.getHideWriteControls()
);
};

const shouldShowUnauthorizedEmptyState = () => {
const readonlyMode =
!appStateData.panels.length &&
!getShouldShowEditHelp() &&
!getShouldShowViewHelp() &&
dashboardConfig.getHideWriteControls();
const userHasNoPermissions =
!appStateData.panels.length && !visualizeCapabilities.save && !mapsCapabilities.save;
return readonlyMode || userHasNoPermissions;
};

const getEmptyScreenProps = (
shouldShowEditHelp: boolean,
isEmptyInReadOnlyMode: boolean
): DashboardEmptyScreenProps => {
const emptyScreenProps: DashboardEmptyScreenProps = {
onLinkClick: () => {}, // TODO
showLinkToVisualize: shouldShowEditHelp,
uiSettings,
http,
};
if (shouldShowEditHelp) {
emptyScreenProps.onVisualizeClick = () => {
alert('click'); // TODO
};
}
if (isEmptyInReadOnlyMode) {
emptyScreenProps.isReadonlyMode = true;
}
return emptyScreenProps;
};
const { dashboardContainer } = useDashboardContainer(

Check warning on line 35 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L35

Added line #L35 was not covered by tests
services,
isChromeVisible,
eventEmitter,
dashboardDom,
savedDashboardInstance,
appState
);

const getDashboardInput = () => {
const embeddablesMap: {
[key: string]: DashboardPanelState;
} = {};
appStateData.panels.forEach((panel: SavedDashboardPanel) => {
embeddablesMap[panel.panelIndex] = convertSavedDashboardPanelToPanelState(panel);
});
const { isEmbeddableRendered, currentAppState } = useEditorUpdates(

Check warning on line 44 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L44

Added line #L44 was not covered by tests
services,
eventEmitter,
savedDashboardInstance,
dashboardContainer,
appState
);

const lastReloadRequestTime = 0;
return {
id: savedDashboardInstance.id || '',
filters: appStateData.filters,
hidePanelTitles: appStateData?.options.hidePanelTitles,
query: appStateData.query,
timeRange: {
..._.cloneDeep(timefilter.getTime()),
},
refreshConfig: timefilter.getRefreshInterval(),
viewMode: appStateData.viewMode,
panels: embeddablesMap,
isFullScreenMode: appStateData?.fullScreenMode,
isEmbeddedExternally: false, // TODO
// isEmptyState: shouldShowEditHelp || shouldShowViewHelp || isEmptyInReadonlyMode,
isEmptyState: false, // TODO
useMargins: appStateData.options.useMargins,
lastReloadRequestTime, // TODO
title: appStateData.title,
description: appStateData.description,
expandedPanelId: appStateData.expandedPanelId,
};
};
useEffect(() => {

Check warning on line 52 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L52

Added line #L52 was not covered by tests
if (dashboardFactory) {
dashboardFactory
.create(getDashboardInput())
.then((container: DashboardContainer | ErrorEmbeddable | undefined) => {
if (container && !isErrorEmbeddable(container)) {
// dashboardContainer = container;
setDashboardContainer(container);

}
});
}
}, [dashboardFactory, getDashboardInput]);

dashboardContainer.renderEmpty = () => {
const shouldShowEditHelp = getShouldShowEditHelp();
const shouldShowViewHelp = getShouldShowViewHelp();
const isEmptyInReadOnlyMode = shouldShowUnauthorizedEmptyState();
const isEmptyState =
shouldShowEditHelp || shouldShowViewHelp || isEmptyInReadOnlyMode;
return isEmptyState ? (
<DashboardEmptyScreen
{...getEmptyScreenProps(shouldShowEditHelp, isEmptyInReadOnlyMode)}
/>
) : null;
};

outputSubscription = merge(
// output of dashboard container itself
dashboardContainer.getOutput$(),
// plus output of dashboard container children,
// children may change, so make sure we subscribe/unsubscribe with switchMap
dashboardContainer.getOutput$().pipe(
map(() => dashboardContainer!.getChildIds()),
distinctUntilChanged(deepEqual),
switchMap((newChildIds: string[]) =>
merge(
...newChildIds.map((childId) =>
dashboardContainer!
.getChild(childId)
.getOutput$()
.pipe(catchError(() => EMPTY))
)
)
)
)
)
.pipe(
mapTo(dashboardContainer),
startWith(dashboardContainer) // to trigger initial index pattern update
// updateIndexPatternsOperator //TODO
)
.subscribe();

inputSubscription = dashboardContainer.getInput$().subscribe((foo) => {
console.log(foo);
});

if (dashboardDom && dashboardContainer) {
console.log('dashboard container inside', dashboardContainer);
dashboardContainer.render(dashboardDom);
}
// clean up all registered listeners if any is left
return () => {
eventEmitter.removeAllListeners();

Check warning on line 55 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L54-L55

Added lines #L54 - L55 were not covered by tests
};
}, [eventEmitter]);

console.log('savedDashboardInstance', savedDashboardInstance);

Check failure on line 59 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux

Unexpected console statement

Check failure on line 59 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Windows

Unexpected console statement
console.log('appState', appState);

Check failure on line 60 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux

Unexpected console statement

Check failure on line 60 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Windows

Unexpected console statement
console.log('currentAppState', currentAppState);

Check failure on line 61 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux

Unexpected console statement

Check failure on line 61 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Windows

Unexpected console statement
console.log('isEmbeddableRendered', isEmbeddableRendered);

Check failure on line 62 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux

Unexpected console statement

Check failure on line 62 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Windows

Unexpected console statement
console.log('dashboardContainer', dashboardContainer);

Check failure on line 63 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux

Unexpected console statement

Check failure on line 63 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View workflow job for this annotation

GitHub Actions / Build and Verify on Windows

Unexpected console statement

Check warning on line 63 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L59-L63

Added lines #L59 - L63 were not covered by tests

return (

Check warning on line 65 in src/plugins/dashboard/public/application/components/dashboard_editor.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_editor.tsx#L65

Added line #L65 was not covered by tests
<div>
{savedDashboardInstance && appState && (
<DashboardTopNav
isChromeVisible={isChromeVisible}
savedDashboardInstance={savedDashboardInstance}
currentAppState={appStateData}
stateContainer={appState}
dashboardContainer={dashboardContainer}
/>
)}
<div>
{savedDashboardInstance && appState && dashboardContainer && currentAppState && (
<DashboardTopNav
isChromeVisible={isChromeVisible}
savedDashboardInstance={savedDashboardInstance}
stateContainer={appState}
currentAppState={currentAppState}
isEmbeddableRendered={isEmbeddableRendered}
dashboardContainer={dashboardContainer}
/>
)}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import { DashboardContainer } from '../embeddable';
interface DashboardTopNavProps {
isChromeVisible: boolean;
savedDashboardInstance: any;
currentAppState: DashboardAppState;
stateContainer: DashboardAppStateContainer;
currentAppState: DashboardAppState;
isEmbeddableRendered: boolean;
dashboardContainer?: DashboardContainer;
}

Expand All @@ -36,8 +37,9 @@ enum UrlParams {
const TopNav = ({
isChromeVisible,
savedDashboardInstance,
currentAppState,
stateContainer,
currentAppState,
isEmbeddableRendered,
dashboardContainer,
}: DashboardTopNavProps) => {
const [filters, setFilters] = useState<Filter[]>([]);
Expand Down Expand Up @@ -66,22 +68,29 @@ const TopNav = ({
}, [services, queryService]);

useEffect(() => {

Check warning on line 70 in src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx#L70

Added line #L70 was not covered by tests
const navActions = getNavActions(
stateContainer,
savedDashboardInstance,
services,
dashboardContainer
);
setTopNavMenu(
getTopNavConfig(currentAppState?.viewMode, navActions, dashboardConfig.getHideWriteControls())
);
if (isEmbeddableRendered) {
const navActions = getNavActions(

Check warning on line 72 in src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx#L72

Added line #L72 was not covered by tests
stateContainer,
savedDashboardInstance,
services,
dashboardContainer
);
setTopNavMenu(

Check warning on line 78 in src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/dashboard/public/application/components/dashboard_top_nav.tsx#L78

Added line #L78 was not covered by tests
getTopNavConfig(
currentAppState?.viewMode,
navActions,
dashboardConfig.getHideWriteControls()
)
);
}
}, [
currentAppState,
services,
dashboardConfig,
dashboardContainer,
savedDashboardInstance,
stateContainer,
isEmbeddableRendered,
]);

useEffect(() => {
Expand Down Expand Up @@ -115,9 +124,9 @@ const TopNav = ({
}*/
}, []);

console.log('currentAppState', currentAppState);
console.log('state container get()', stateContainer.get());
console.log('dashboard container top nav', dashboardContainer);
// console.log('currentAppState', currentAppState);
// console.log('state container get()', stateContainer.get());
// console.log('dashboard container top nav', dashboardContainer);
return isChromeVisible ? (
<TopNavMenu
appName={'dashboard'}
Expand Down
Loading

0 comments on commit 526e3d6

Please sign in to comment.