Skip to content

Commit

Permalink
refactor: Improve GL item config types (#2138)
Browse files Browse the repository at this point in the history
- Broke out explicit `ItemConfig` sub types and converted `ItemConfig`
type into a union them all
- Updated `createContentItem` to be more explicit in its mapping of
config types to returned content items
- Updated references to `ItemConfigType` with `ItemConfig`
- Updated `Component`, `RowOrColumn`, and `Stack` classes to allow null
`parent`

resolves #2130
  • Loading branch information
bmingles authored Jul 12, 2024
1 parent 011eb33 commit 0da547d
Show file tree
Hide file tree
Showing 21 changed files with 273 additions and 180 deletions.
4 changes: 2 additions & 2 deletions packages/app-utils/src/components/AppDashboards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import {
useObjectFetcher,
} from '@deephaven/jsapi-bootstrap';
import LayoutManager, {
ItemConfigType,
ItemConfig,
Settings as LayoutSettings,
} from '@deephaven/golden-layout';
import { LoadingOverlay } from '@deephaven/components';

interface AppDashboardsProps {
dashboards: {
id: string;
layoutConfig: ItemConfigType[];
layoutConfig: ItemConfig[];
layoutSettings?: Partial<LayoutSettings>;
key?: string;
}[];
Expand Down
6 changes: 3 additions & 3 deletions packages/app-utils/src/storage/LayoutStorage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { ItemConfigType } from '@deephaven/golden-layout';
import type { ItemConfig } from '@deephaven/golden-layout';
import { FilterSet, Link } from '@deephaven/dashboard-core-plugins';
import { PluginDataMap } from '@deephaven/redux';

/**
* Have a different version to support legacy layout exports
*/
export type ExportedLayoutV1 = ItemConfigType[];
export type ExportedLayoutV1 = ItemConfig[];

export type ExportedLayoutV2 = {
filterSets: FilterSet[];
links: Link[];
layoutConfig: ItemConfigType[];
layoutConfig: ItemConfig[];
pluginDataMap?: PluginDataMap;
version: 2;
};
Expand Down
4 changes: 2 additions & 2 deletions packages/app-utils/src/storage/UserLayoutUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FilterSet, Link } from '@deephaven/dashboard-core-plugins';
import type { ItemConfigType } from '@deephaven/golden-layout';
import type { ItemConfig } from '@deephaven/golden-layout';
import LayoutStorage, {
ExportedLayout,
ExportedLayoutV1,
Expand Down Expand Up @@ -28,7 +28,7 @@ const filterSets: FilterSet[] = [
panels: [],
},
];
const layoutConfig: ItemConfigType[] = [
const layoutConfig: ItemConfig[] = [
{
component: 'TestComponent',
type: 'TestComponentType',
Expand Down
8 changes: 4 additions & 4 deletions packages/code-studio/src/main/AppMainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import {
EMPTY_ARRAY,
} from '@deephaven/utils';
import GoldenLayout from '@deephaven/golden-layout';
import type { ItemConfigType } from '@deephaven/golden-layout';
import type { ItemConfig } from '@deephaven/golden-layout';
import { type PluginModuleMap, getDashboardPlugins } from '@deephaven/plugin';
import {
AppDashboards,
Expand Down Expand Up @@ -755,7 +755,7 @@ export class AppMainContainer extends Component<

getDashboards(): {
id: string;
layoutConfig: ItemConfigType[];
layoutConfig: ItemConfig[];
key?: string;
}[] {
const { layoutIteration, tabs } = this.state;
Expand All @@ -766,15 +766,15 @@ export class AppMainContainer extends Component<
return [
{
id: DEFAULT_DASHBOARD_ID,
layoutConfig: layoutConfig as ItemConfigType[],
layoutConfig: layoutConfig as ItemConfig[],
key: `${DEFAULT_DASHBOARD_ID}-${layoutIteration}`,
},
...tabs
.filter(tab => tab.key !== DEFAULT_DASHBOARD_ID)
.map(tab => ({
id: tab.key,
layoutConfig: (allDashboardData[tab.key]?.layoutConfig ??
EMPTY_ARRAY) as ItemConfigType[],
EMPTY_ARRAY) as ItemConfig[],
key: `${tab.key}-${layoutIteration}`,
})),
];
Expand Down
4 changes: 2 additions & 2 deletions packages/dashboard/src/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, {
} from 'react';
import throttle from 'lodash.throttle';
import GoldenLayout from '@deephaven/golden-layout';
import type { ItemConfigType } from '@deephaven/golden-layout';
import type { ItemConfig } from '@deephaven/golden-layout';
import { useResizeObserver } from '@deephaven/react-hooks';
import './layout/GoldenLayout.scss';
import LayoutUtils from './layout/LayoutUtils';
Expand All @@ -33,7 +33,7 @@ export type DashboardProps = {
id?: string;
children?: React.ReactNode | React.ReactNode[];
emptyDashboard?: React.ReactNode;
layoutConfig?: ItemConfigType[];
layoutConfig?: ItemConfig[];
layoutSettings?: Record<string, unknown>;
onLayoutConfigChange?: () => void;
onGoldenLayoutChange?: (goldenLayout: GoldenLayout) => void;
Expand Down
4 changes: 2 additions & 2 deletions packages/dashboard/src/DashboardLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
import GoldenLayout from '@deephaven/golden-layout';
import type {
Container,
ItemConfigType,
ItemConfig,
ReactComponentConfig,
} from '@deephaven/golden-layout';
import Log from '@deephaven/log';
Expand All @@ -37,7 +37,7 @@ import {
} from './DashboardPlugin';
import DashboardPanelWrapper from './DashboardPanelWrapper';

export type DashboardLayoutConfig = ItemConfigType[];
export type DashboardLayoutConfig = ItemConfig[];

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

Expand Down
6 changes: 3 additions & 3 deletions packages/dashboard/src/PanelManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import GoldenLayout from '@deephaven/golden-layout';
import type {
Container,
ContentItem,
ItemConfigType,
ItemConfig,
ReactComponentConfig,
} from '@deephaven/golden-layout';
import Log from '@deephaven/log';
Expand Down Expand Up @@ -139,7 +139,7 @@ class PanelManager {
return Array.from(this.openedMap.values());
}

getOpenedPanelConfigs(): (ItemConfigType | null)[] {
getOpenedPanelConfigs(): (ItemConfig | null)[] {
return this.getOpenedPanels().map(panel => {
const { glContainer } = panel.props;
return LayoutUtils.getComponentConfigFromContainer(glContainer);
Expand Down Expand Up @@ -278,7 +278,7 @@ class PanelManager {
*/
handleReopen(
panelConfig: ClosedPanel,
replaceConfig?: Partial<ItemConfigType>
replaceConfig?: Partial<ItemConfig>
): void {
log.debug2('Reopen:', panelConfig, replaceConfig);

Expand Down
45 changes: 25 additions & 20 deletions packages/dashboard/src/layout/LayoutUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {
Container,
ContentItem,
ItemConfig,
ItemConfigType,
ReactComponentConfig,
Stack,
Tab,
Expand All @@ -38,12 +37,12 @@ export type StackItemConfig = ItemConfig & {
activeItemIndex?: number;
};

function isComponentConfig(config: ItemConfigType): config is ComponentConfig {
function isComponentConfig(config: ItemConfig): config is ComponentConfig {
return (config as ComponentConfig).componentName !== undefined;
}

export function isReactComponentConfig(
config: ItemConfigType
config: ItemConfig
): config is ReactComponentConfig {
const reactConfig = config as ReactComponentConfig;
// Golden layout sets the type to 'component' and componentName to 'lm-react-component' in `createContentItem`, then changes it back in `toConfig`
Expand All @@ -60,13 +59,13 @@ function isHTMLElement(element: Element): element is HTMLElement {
return (element as HTMLElement).focus !== undefined;
}

function isStackItemConfig(config: ItemConfigType): config is StackItemConfig {
function isStackItemConfig(config: ItemConfig): config is StackItemConfig {
return config.type === 'stack';
}
class LayoutUtils {
static DEFAULT_FOCUS_SELECTOR = 'input, select, textarea, button';

static activateTab(root: ContentItem, config: Partial<ItemConfigType>): void {
static activateTab(root: ContentItem, config: Partial<ItemConfig>): void {
const stack = LayoutUtils.getStackForRoot(root, config, false);
if (!stack) {
log.error('Could not find stack for config', config);
Expand Down Expand Up @@ -106,17 +105,20 @@ class LayoutUtils {
* @returns The newly created stack.
*/
static addStack(parent: ContentItem, columnPreferred = true): Stack {
const type = columnPreferred ? 'column' : 'row';
if (isRoot(parent)) {
const rowOrColConfig: ItemConfig = {
type: columnPreferred ? 'column' : 'row',
};

if (parent.contentItems == null || parent.contentItems.length === 0) {
parent.addChild({ type });
parent.addChild(rowOrColConfig);
}

const child = parent.contentItems[0];
const isCorrectType = columnPreferred ? child.isColumn : child.isRow;
if (!isCorrectType) {
parent.removeChild(child, true);
parent.addChild({ type });
parent.addChild(rowOrColConfig);

// The addChild may cause the element that has focus to be removed from the DOM, which changes focus to the body
// Try and maintain the focus as best we can. The unfocused element may still send a blur/focus event so that needs to be handled correctly.
Expand All @@ -142,7 +144,10 @@ class LayoutUtils {
? newParent.isColumn
: newParent.isRow;
if (!isCorrectType) {
parent.addChild({ type: !columnPreferred ? 'column' : 'row' });
const inverseRowOrColConfig: ItemConfig = {
type: !columnPreferred ? 'column' : 'row',
};
parent.addChild(inverseRowOrColConfig);
parent.removeChild(newParent, true);
parent.contentItems[parent.contentItems.length - 1].addChild(newParent);
newParent = parent.contentItems[parent.contentItems.length - 1];
Expand Down Expand Up @@ -197,7 +202,7 @@ class LayoutUtils {
*/
static getStackForConfig(
item: ContentItem,
config: Partial<ItemConfigType> = {},
config: Partial<ItemConfig> = {},
allowEmptyStack = false
): Stack | null {
if (allowEmptyStack && isStack(item) && item.contentItems.length === 0) {
Expand Down Expand Up @@ -239,7 +244,7 @@ class LayoutUtils {
*/
static getStackForRoot(
root: ContentItem,
config: Partial<ReactComponentConfig>,
config: Partial<ItemConfig>,
createIfNecessary = true,
matchComponentType = true,
allowEmptyStack = true
Expand All @@ -248,7 +253,7 @@ class LayoutUtils {
if (!stack && matchComponentType) {
stack = this.getStackForConfig(
root,
{ component: config.component },
{ component: (config as { component?: string }).component },
allowEmptyStack
);
}
Expand Down Expand Up @@ -300,7 +305,7 @@ class LayoutUtils {
*/
static getContentItemInStack(
stack: ContentItem | null,
config: Partial<ItemConfigType>
config: Partial<ItemConfig>
): ContentItem | null {
if (!stack) {
return null;
Expand All @@ -322,10 +327,10 @@ class LayoutUtils {
* @returns Dehydrated config
*/
static dehydrateLayoutConfig(
config: ItemConfigType[],
config: ItemConfig[],
dehydrateComponent: (
componentName: string,
config: ItemConfigType
config: ItemConfig
) => PanelConfig
): (PanelConfig | ItemConfig)[] {
if (config == null || !config.length) {
Expand Down Expand Up @@ -516,7 +521,7 @@ class LayoutUtils {
config?: Partial<ReactComponentConfig>;
stack?: Stack;
replaceExisting?: boolean;
replaceConfig?: Partial<ItemConfigType>;
replaceConfig?: Partial<ItemConfig>;
createNewStack?: boolean;
focusElement?: string;
dragEvent?: DragEvent;
Expand Down Expand Up @@ -600,7 +605,7 @@ class LayoutUtils {
*/
static openComponentInStack(
stack: Stack | null,
config: ItemConfigType & Record<string, unknown>,
config: ItemConfig & Record<string, unknown>,
replaceExisting = true
): void {
const maintainFocusElement = document.activeElement; // attempt to retain focus after dom manipulation, which can break focus
Expand Down Expand Up @@ -676,7 +681,7 @@ class LayoutUtils {

static renameComponent(
root: ContentItem,
config: Partial<ItemConfigType>,
config: Partial<ItemConfig>,
newTitle: string
): void {
const stack = LayoutUtils.getStackForRoot(root, config, false);
Expand Down Expand Up @@ -727,7 +732,7 @@ class LayoutUtils {
* @param config Panel config
* @returns Panel state
*/
static getPanelComponentState(config: ItemConfigType): unknown {
static getPanelComponentState(config: ItemConfig): unknown {
if (isComponentConfig(config)) {
return config.componentState?.panelState;
}
Expand Down Expand Up @@ -766,7 +771,7 @@ class LayoutUtils {
*/
static getComponentConfigFromContainer(
container?: Container
): ItemConfigType | null {
): ItemConfig | null {
if (container) {
if (container.tab != null && container.tab.contentItem != null) {
return container.tab.contentItem.config;
Expand Down
6 changes: 3 additions & 3 deletions packages/embed-widget/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
useUser,
} from '@deephaven/app-utils';
import type GoldenLayout from '@deephaven/golden-layout';
import type { ItemConfigType } from '@deephaven/golden-layout';
import type { ItemConfig } from '@deephaven/golden-layout';
import {
ContextMenuRoot,
ErrorBoundary,
Expand Down Expand Up @@ -201,10 +201,10 @@ function App(): JSX.Element {
const dashboardPlugins = useDashboardPlugins();

const layoutConfig = (allDashboardData[dashboardId]?.layoutConfig ??
EMPTY_ARRAY) as ItemConfigType[];
EMPTY_ARRAY) as ItemConfig[];

const hasMultipleComponents = useMemo(() => {
function getComponentCount(config: ItemConfigType[]) {
function getComponentCount(config: ItemConfig[]) {
if (config.length === 0) {
return 0;
}
Expand Down
Loading

0 comments on commit 0da547d

Please sign in to comment.