Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add DashboardPlugin support to embed-widget #1950

Merged
merged 3 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/app-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@deephaven/console": "file:../console",
"@deephaven/dashboard": "file:../dashboard",
"@deephaven/dashboard-core-plugins": "file:../dashboard-core-plugins",
"@deephaven/golden-layout": "file:../golden-layout",
"@deephaven/icons": "file:../icons",
"@deephaven/iris-grid": "file:../iris-grid",
"@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap",
Expand All @@ -48,6 +49,7 @@
"@deephaven/utils": "file:../utils",
"@paciolan/remote-component": "2.13.0",
"@paciolan/remote-module-loader": "^3.0.2",
"classnames": "^2.5.1",
"fira": "mozilla/fira#4.202"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,40 @@ import React, { useCallback } from 'react';
import classNames from 'classnames';
import {
DashboardUtils,
DEFAULT_DASHBOARD_ID,
DehydratedDashboardPanelProps,
LazyDashboard,
} from '@deephaven/dashboard';
import {
sanitizeVariableDescriptor,
useObjectFetcher,
} from '@deephaven/jsapi-bootstrap';
import LayoutManager, { ItemConfigType } from '@deephaven/golden-layout';
import LayoutManager, {
ItemConfigType,
Settings as LayoutSettings,
} from '@deephaven/golden-layout';
import { LoadingOverlay } from '@deephaven/components';
import EmptyDashboard from './EmptyDashboard';

interface AppDashboardsProps {
dashboards: {
id: string;
layoutConfig: ItemConfigType[];
layoutSettings?: Partial<LayoutSettings>;
key?: string;
}[];
activeDashboard: string;
onLayoutInitialized?: () => void;
onGoldenLayoutChange: (goldenLayout: LayoutManager) => void;
plugins: JSX.Element[];
onAutoFillClick: (event: React.MouseEvent) => void;
emptyDashboard?: JSX.Element;
}

export function AppDashboards({
dashboards,
activeDashboard,
onLayoutInitialized,
onGoldenLayoutChange,
plugins,
onAutoFillClick,
emptyDashboard = <LoadingOverlay />,
}: AppDashboardsProps): JSX.Element {
const fetchObject = useObjectFetcher();

Expand Down Expand Up @@ -68,14 +72,10 @@ export function AppDashboards({
id={d.id}
key={d.key}
isActive={d.id === activeDashboard}
emptyDashboard={
d.id === DEFAULT_DASHBOARD_ID ? (
<EmptyDashboard onAutoFillClick={onAutoFillClick} />
) : (
<LoadingOverlay />
)
}
emptyDashboard={emptyDashboard}
layoutConfig={d.layoutConfig}
layoutSettings={d.layoutSettings}
onLayoutInitialized={onLayoutInitialized}
onGoldenLayoutChange={onGoldenLayoutChange}
hydrate={hydratePanel}
plugins={plugins}
Expand Down
1 change: 1 addition & 0 deletions packages/app-utils/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './AppBootstrap';
export * from './AppDashboards';
export * from './AuthBootstrap';
export * from './ConnectionBootstrap';
export * from './ConnectionContext';
Expand Down
39 changes: 14 additions & 25 deletions packages/code-studio/src/main/AppMainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
NavTabList,
type NavTabItem,
SlideTransition,
LoadingOverlay,
} from '@deephaven/components';
import { SHORTCUTS as IRIS_GRID_SHORTCUTS } from '@deephaven/iris-grid';
import {
Expand Down Expand Up @@ -88,13 +89,8 @@ import {
} from '@deephaven/utils';
import GoldenLayout from '@deephaven/golden-layout';
import type { ItemConfigType } from '@deephaven/golden-layout';
import {
type DashboardPlugin,
isDashboardPlugin,
type LegacyDashboardPlugin,
isLegacyDashboardPlugin,
type PluginModuleMap,
} from '@deephaven/plugin';
import { type PluginModuleMap, getDashboardPlugins } from '@deephaven/plugin';
import { AppDashboards } from '@deephaven/app-utils';
import JSZip from 'jszip';
import SettingsMenu from '../settings/SettingsMenu';
import AppControlsMenu from './AppControlsMenu';
Expand All @@ -103,8 +99,8 @@ import './AppMainContainer.scss';
import WidgetList, { WindowMouseEvent } from './WidgetList';
import UserLayoutUtils from './UserLayoutUtils';
import LayoutStorage from '../storage/LayoutStorage';
import AppDashboards from './AppDashboards';
import { getFormattedVersionInfo } from '../settings/SettingsUtils';
import EmptyDashboard from './EmptyDashboard';

const log = Log.module('AppMainContainer');

Expand Down Expand Up @@ -783,22 +779,9 @@ export class AppMainContainer extends Component<
});
}

getDashboardPlugins = memoize((plugins: PluginModuleMap) => {
const dashboardPlugins = [...plugins.entries()].filter(
([, plugin]) =>
isDashboardPlugin(plugin) || isLegacyDashboardPlugin(plugin)
) as [string, DashboardPlugin | LegacyDashboardPlugin][];

return dashboardPlugins.map(([name, plugin]) => {
if (isLegacyDashboardPlugin(plugin)) {
const { DashboardPlugin: DPlugin } = plugin;
return <DPlugin key={name} />;
}

const { component: DPlugin } = plugin;
return <DPlugin key={name} />;
});
});
getDashboardPlugins = memoize((plugins: PluginModuleMap) =>
getDashboardPlugins(plugins)
);

handleHomeClick(): void {
this.handleTabSelect(DEFAULT_DASHBOARD_ID);
Expand Down Expand Up @@ -998,7 +981,13 @@ export class AppMainContainer extends Component<
dashboards={this.getDashboards()}
activeDashboard={activeTabKey}
onGoldenLayoutChange={this.handleGoldenLayoutChange}
onAutoFillClick={this.handleAutoFillClick}
emptyDashboard={
activeTabKey === DEFAULT_DASHBOARD_ID ? (
<EmptyDashboard onAutoFillClick={this.handleAutoFillClick} />
) : (
<LoadingOverlay />
)
}
plugins={[
<ConsolePlugin
key="ConsolePlugin"
Expand Down
6 changes: 5 additions & 1 deletion packages/dashboard/src/DashboardEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export function stopListenForCreateDashboard<T = unknown>(
eventHub: EventHub,
handler: (p: CreateDashboardPayload<T>) => void
): void {
eventHub.off(CREATE_DASHBOARD, handler);
try {
eventHub.off(CREATE_DASHBOARD, handler);
} catch {
// golden-layout throws if the handler is not found. Instead catch it and no-op
}
}

export function listenForCreateDashboard<T = unknown>(
Expand Down
12 changes: 7 additions & 5 deletions packages/dashboard/src/DashboardLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ export function DashboardLayout({
layout.getReactChildren()
);

// Fire only once after the layout is mounted
// This should ensure DashboardPlugins have been mounted
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => onLayoutInitialized(), []);

const hydrateMap = useMemo(() => new Map(), []);
const dehydrateMap = useMemo(() => new Map(), []);
const registerComponent = useCallback(
Expand Down Expand Up @@ -320,6 +315,13 @@ export function DashboardLayout({
]
);

// This should be the last hook called in this component
// Ensures it runs after any other effects on mount
// Fire only once after the layout is mounted
// This should ensure DashboardPlugins have been mounted
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => onLayoutInitialized(), []);

return (
<>
{isDashboardEmpty && emptyDashboard}
Expand Down
7 changes: 6 additions & 1 deletion packages/embed-widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,21 @@
"dependencies": {
"@deephaven/app-utils": "file:../app-utils",
"@deephaven/components": "file:../components",
"@deephaven/dashboard": "file:../dashboard",
"@deephaven/dashboard-core-plugins": "file:../dashboard-core-plugins",
"@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap",
"@deephaven/jsapi-components": "file:../jsapi-components",
"@deephaven/jsapi-types": "1.0.0-dev0.33.1",
"@deephaven/jsapi-utils": "file:../jsapi-utils",
"@deephaven/log": "file:../log",
"@deephaven/plugin": "file:../plugin",
"@deephaven/redux": "file:../redux",
"@deephaven/utils": "file:../utils",
"fira": "mozilla/fira#4.202",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"shortid": "^2.2.16"
},
"scripts": {
"analyze": "source-map-explorer build/assets/*.js --no-border-checks",
Expand Down
37 changes: 37 additions & 0 deletions packages/embed-widget/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,43 @@
left: 0;
right: 0;
bottom: 0;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
overflow: hidden;
}

$tab-height: 32px;
$tab-font-size: 1rem;

$tab-button-side-padding: 9px;

$tab-link-disabled-color: $gray-600;

$nav-space: 4px; // give a gap around some buttons for focus area that are in nav bar

.app-main-top-nav-menus {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}

.tab-content {
flex-grow: 1;
height: 100%;
}

.tab-pane {
height: 100%;
width: 100%;
flex-grow: 1;
}

.app-main-tabs {
&:focus {
outline: none;
}
}
Loading
Loading