Skip to content

Commit 83234d6

Browse files
committed
Merge branch 'main' into feature-1151-table-rendering-support-for-databars
2 parents c537c41 + 85ce600 commit 83234d6

16 files changed

Lines changed: 433 additions & 39 deletions

File tree

package-lock.json

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/code-studio/src/main/AppInit.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
setDashboardData as setDashboardDataAction,
1212
} from '@deephaven/dashboard';
1313
import {
14+
SessionDetails,
1415
SessionWrapper,
1516
setDashboardConnection as setDashboardConnectionAction,
1617
setDashboardSessionWrapper as setDashboardSessionWrapperAction,
@@ -52,6 +53,7 @@ import {
5253
createSessionWrapper,
5354
getAuthType,
5455
getLoginOptions,
56+
getSessionDetails,
5557
} from './SessionUtils';
5658
import { PluginUtils } from '../plugins';
5759
import LayoutStorage from '../storage/LayoutStorage';
@@ -98,11 +100,12 @@ async function loadPlugins(): Promise<DeephavenPluginModuleMap> {
98100
}
99101

100102
async function loadSessionWrapper(
101-
connection: IdeConnection
103+
connection: IdeConnection,
104+
sessionDetails: SessionDetails
102105
): Promise<SessionWrapper | undefined> {
103106
let sessionWrapper: SessionWrapper | undefined;
104107
try {
105-
sessionWrapper = await createSessionWrapper(connection);
108+
sessionWrapper = await createSessionWrapper(connection, sessionDetails);
106109
} catch (e) {
107110
// Consoles may be disabled on the server, but we should still be able to start up and open existing objects
108111
if (!isNoConsolesError(e)) {
@@ -170,7 +173,11 @@ function AppInit(props: AppInitProps) {
170173
const coreClient = createCoreClient();
171174
const authType = getAuthType();
172175
log.info(`Login using auth type ${authType}...`);
173-
await coreClient.login(await getLoginOptions(authType));
176+
const [loginOptions, sessionDetails] = await Promise.all([
177+
getLoginOptions(authType),
178+
getSessionDetails(authType),
179+
]);
180+
await coreClient.login(loginOptions);
174181

175182
const newPlugins = await loadPlugins();
176183
const connection = await (authType === AUTH_TYPE.ANONYMOUS &&
@@ -185,7 +192,10 @@ function AppInit(props: AppInitProps) {
185192
setDisconnectError(null);
186193
});
187194

188-
const sessionWrapper = await loadSessionWrapper(connection);
195+
const sessionWrapper = await loadSessionWrapper(
196+
connection,
197+
sessionDetails
198+
);
189199
const name = 'user';
190200

191201
const storageService = coreClient.getStorageService();

packages/code-studio/src/main/SessionUtils.ts

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
import { SessionWrapper } from '@deephaven/dashboard-core-plugins';
1+
import {
2+
SessionDetails,
3+
SessionWrapper,
4+
} from '@deephaven/dashboard-core-plugins';
25
import dh, {
36
CoreClient,
47
IdeConnection,
58
LoginOptions,
69
} from '@deephaven/jsapi-shim';
10+
import {
11+
LOGIN_OPTIONS_REQUEST,
12+
requestParentResponse,
13+
SESSION_DETAILS_REQUEST,
14+
} from '@deephaven/jsapi-utils';
715
import Log from '@deephaven/log';
816
import shortid from 'shortid';
917
import NoConsolesError from './NoConsolesError';
@@ -50,7 +58,8 @@ export function createConnection(): IdeConnection {
5058
* @returns A session and config that is ready to use
5159
*/
5260
export async function createSessionWrapper(
53-
connection: IdeConnection
61+
connection: IdeConnection,
62+
details: SessionDetails
5463
): Promise<SessionWrapper> {
5564
log.info('Getting console types...');
5665

@@ -72,7 +81,12 @@ export async function createSessionWrapper(
7281

7382
log.info('Console session established', config);
7483

75-
return { session, config, connection };
84+
return {
85+
session,
86+
config,
87+
connection,
88+
details,
89+
};
7690
}
7791

7892
export function createCoreClient(): CoreClient {
@@ -83,29 +97,12 @@ export function createCoreClient(): CoreClient {
8397
return new dh.CoreClient(websocketUrl);
8498
}
8599

86-
export async function requestParentLoginOptions(): Promise<LoginOptions> {
87-
if (window.opener == null) {
88-
throw new Error('window.opener is null, unable to send auth request.');
89-
}
90-
return new Promise(resolve => {
91-
const listener = (
92-
event: MessageEvent<{
93-
message: string;
94-
payload: LoginOptions;
95-
}>
96-
) => {
97-
const { data } = event;
98-
log.debug('Received message', data);
99-
if (data?.message !== 'loginOptions') {
100-
log.debug('Ignore received message', data);
101-
return;
102-
}
103-
window.removeEventListener('message', listener);
104-
resolve(data.payload);
105-
};
106-
window.addEventListener('message', listener);
107-
window.opener.postMessage('requestLoginOptionsFromParent', '*');
108-
});
100+
async function requestParentLoginOptions(): Promise<LoginOptions> {
101+
return requestParentResponse<LoginOptions>(LOGIN_OPTIONS_REQUEST);
102+
}
103+
104+
async function requestParentSessionDetails(): Promise<SessionDetails> {
105+
return requestParentResponse<SessionDetails>(SESSION_DETAILS_REQUEST);
109106
}
110107

111108
export async function getLoginOptions(
@@ -121,4 +118,17 @@ export async function getLoginOptions(
121118
}
122119
}
123120

121+
export async function getSessionDetails(
122+
authType: AUTH_TYPE
123+
): Promise<SessionDetails> {
124+
switch (authType) {
125+
case AUTH_TYPE.PARENT:
126+
return requestParentSessionDetails();
127+
case AUTH_TYPE.ANONYMOUS:
128+
return {};
129+
default:
130+
throw new Error(`Unknown auth type: ${authType}`);
131+
}
132+
}
133+
124134
export default { createSessionWrapper };

packages/dashboard-core-plugins/src/panels/ConsolePanel.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,8 @@ export class ConsolePanel extends PureComponent<
320320
unzip,
321321
} = this.props;
322322
const { consoleSettings, error, objectMap } = this.state;
323-
const { config, session, connection } = sessionWrapper;
323+
const { config, session, connection, details = {} } = sessionWrapper;
324+
const { workerName, processInfoId } = details;
324325
const { id: sessionId, type: language } = config;
325326

326327
return (
@@ -349,6 +350,19 @@ export class ConsolePanel extends PureComponent<
349350
<>
350351
<div>&nbsp;</div>
351352
<div>{ConsoleConstants.LANGUAGE_MAP.get(language)}</div>
353+
{workerName != null && (
354+
<>
355+
<div>&nbsp;•&nbsp;</div>
356+
{workerName}
357+
</>
358+
)}
359+
{processInfoId != null && (
360+
<>
361+
<div>&nbsp;•&nbsp;</div>
362+
{processInfoId}
363+
<div>&nbsp;•</div>
364+
</>
365+
)}
352366
<div>&nbsp;</div>
353367
<div>
354368
<HeapUsage

packages/dashboard-core-plugins/src/redux/actions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ export interface SessionConfig {
1414
id: string;
1515
}
1616

17+
export interface SessionDetails {
18+
workerName?: string;
19+
processInfoId?: string;
20+
}
21+
1722
export interface SessionWrapper {
1823
session: IdeSession;
1924
connection: IdeConnection;
2025
config: SessionConfig;
26+
details?: SessionDetails;
2127
}
2228

2329
/**

packages/dashboard/src/DashboardPlugin.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { Component, ComponentType } from 'react';
1+
import {
2+
Component,
3+
ComponentType,
4+
ForwardRefExoticComponent,
5+
PropsWithoutRef,
6+
RefAttributes,
7+
} from 'react';
28
import { ConnectedComponent } from 'react-redux';
39
import GoldenLayout from '@deephaven/golden-layout';
410
import type {
@@ -8,6 +14,34 @@ import type {
814
} from '@deephaven/golden-layout';
915
import PanelManager from './PanelManager';
1016

17+
/**
18+
* Alias for the return type of React.forwardRef()
19+
*/
20+
export type ForwardRefComponentType<P, R> = ForwardRefExoticComponent<
21+
PropsWithoutRef<P> & RefAttributes<R>
22+
>;
23+
24+
/**
25+
* Panel components can provide static props that provide meta data about the
26+
* panel.
27+
*/
28+
export interface PanelStaticMetaData {
29+
/**
30+
* Should be set to the same name as the component type.
31+
* @deprecated Use `displayName` instead.
32+
*/
33+
COMPONENT?: string;
34+
35+
/** Title of the panel. */
36+
TITLE?: string;
37+
}
38+
39+
/**
40+
* Panels defined as functional components have to use React.forwardRef.
41+
*/
42+
export type PanelFunctionComponentType<P, R> = ForwardRefComponentType<P, R> &
43+
PanelStaticMetaData;
44+
1145
export type WrappedComponentType<
1246
P extends PanelProps,
1347
C extends ComponentType<P>
@@ -16,7 +50,12 @@ export type WrappedComponentType<
1650
export type PanelComponentType<
1751
P extends PanelProps = PanelProps,
1852
C extends ComponentType<P> = ComponentType<P>
19-
> = ComponentType<P> | WrappedComponentType<P, C>;
53+
> = (
54+
| ComponentType<P>
55+
| WrappedComponentType<P, C>
56+
| PanelFunctionComponentType<P, unknown>
57+
) &
58+
PanelStaticMetaData;
2059

2160
export function isWrappedComponent<
2261
P extends PanelProps,

packages/dashboard/src/layout/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export { default as LayoutUtils } from './LayoutUtils';
33
export { default as GLPropTypes } from './GLPropTypes';
44

55
export * from './hooks';
6+
export { default as usePanelRegistration } from './usePanelRegistration';
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* eslint-disable max-classes-per-file */
2+
import React from 'react';
3+
import { renderHook } from '@testing-library/react-hooks';
4+
import usePanelRegistration from './usePanelRegistration';
5+
import { PanelProps } from '../DashboardPlugin';
6+
7+
/* eslint-disable react/prefer-stateless-function */
8+
class ClassCOMPONENT extends React.Component<PanelProps> {
9+
static COMPONENT = 'ClassCOMPONENT';
10+
}
11+
class ClassDisplayName extends React.Component<PanelProps> {
12+
static displayName = 'ClassDisplayName';
13+
}
14+
class ClassNoName extends React.Component<PanelProps> {}
15+
/* eslint-enable react/prefer-stateless-function */
16+
17+
function FnCOMPONENT() {
18+
return null;
19+
}
20+
FnCOMPONENT.COMPONENT = 'FnCOMPONENT';
21+
function FnDisplayName() {
22+
return null;
23+
}
24+
FnDisplayName.displayName = 'FnDisplayName';
25+
function FnNoName() {
26+
return null;
27+
}
28+
29+
const deregister = jest.fn();
30+
const registerComponent = jest.fn();
31+
const hydrate = jest.fn();
32+
const dehydrate = jest.fn();
33+
34+
beforeEach(() => {
35+
jest.clearAllMocks();
36+
registerComponent.mockReturnValue(deregister);
37+
});
38+
39+
it.each([
40+
[ClassCOMPONENT.COMPONENT, ClassCOMPONENT],
41+
[ClassDisplayName.displayName, ClassDisplayName],
42+
[FnCOMPONENT.COMPONENT, FnCOMPONENT],
43+
[FnDisplayName.displayName, FnDisplayName],
44+
])(
45+
'should register components with COMPONENT or displayName attributes and deregister on unmount: "%s"',
46+
(_label, ComponentType) => {
47+
const { unmount } = renderHook(() =>
48+
usePanelRegistration(registerComponent, ComponentType, hydrate, dehydrate)
49+
);
50+
51+
const name =
52+
'COMPONENT' in ComponentType
53+
? ComponentType.COMPONENT
54+
: ComponentType.displayName;
55+
56+
expect(registerComponent).toHaveBeenCalledWith(
57+
name,
58+
ComponentType,
59+
hydrate,
60+
dehydrate
61+
);
62+
63+
expect(deregister).not.toHaveBeenCalled();
64+
65+
unmount();
66+
67+
expect(deregister).toHaveBeenCalled();
68+
}
69+
);
70+
71+
it.each([
72+
['MockClassNoName', ClassNoName],
73+
['MockFnNoName', FnNoName],
74+
])(
75+
'should throw an error if no COMPONENT or displayName attribute exists: "%s"',
76+
(_label, ComponentType) => {
77+
const { result } = renderHook(() =>
78+
usePanelRegistration(registerComponent, ComponentType, hydrate, dehydrate)
79+
);
80+
81+
expect(result.error).toEqual(
82+
new Error(
83+
'ComponentType must have a `COMPONENT` or `displayName` attribute.'
84+
)
85+
);
86+
}
87+
);

0 commit comments

Comments
 (0)