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: Split GroupTree into GroupTreePlot-component and settings #1794

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
102abd7
Backup of initial splitting
jorgenherje Nov 22, 2023
af06af9
Next iteration - WIP
jorgenherje Nov 23, 2023
ef90e96
Update types
jorgenherje Nov 24, 2023
42f1f47
Backup of moving files
jorgenherje Nov 27, 2023
764f98b
Moved group-tree to python folder, have group-tree-plot as package
jorgenherje Nov 27, 2023
3047348
Convert tsx -> jsx due to dash generate component issue
jorgenherje Nov 28, 2023
a92132b
Remove tests+stories in /python. Add story in /typscript/package - WIP
jorgenherje Nov 29, 2023
80bc93d
Remove unwanted autogenerated file
jorgenherje Nov 29, 2023
16502f4
Adjust typing in example data
jorgenherje Nov 29, 2023
e84b65e
Remove test scripts and config
jorgenherje Nov 29, 2023
0931e8e
Deep clone dated trees as it is mutated within assembler
jorgenherje Nov 29, 2023
eb85810
Fix usage of HTML element id
jorgenherje Nov 29, 2023
058eee1
Remove unused code
jorgenherje Nov 29, 2023
233bf43
Adjust storybook config
jorgenherje Nov 29, 2023
9786b09
Add comments/description to Storybook + minor adjustments
jorgenherje Dec 1, 2023
a0e2609
Fix groupTreeAssembler bug found using storybook
jorgenherje Dec 1, 2023
952cbdc
Bug fix and adjust storybook
jorgenherje Dec 5, 2023
6be5794
Revert usage of select for control of strings in storybook
jorgenherje Dec 5, 2023
8ad3541
Remove old typescript/package from packalge-lock.json
jorgenherje Dec 6, 2023
8d77356
Merge branch 'master' into split-group-tree-settings-and-view
jorgenherje Dec 12, 2023
e3f1116
Adjustments after review + formatting
jorgenherje Dec 12, 2023
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
39 changes: 16 additions & 23 deletions python/package-lock.json

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

2 changes: 1 addition & 1 deletion python/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@mui/material": "^5.11",
"@reduxjs/toolkit": "^1.7.2",
"@webviz/core-components": "^0.6.2",
"@webviz/group-tree": "file:../typescript/packages/group-tree",
"@webviz/group-tree-plot": "file:../typescript/packages/group-tree-plot",
"@webviz/subsurface-viewer": "file:../typescript/packages/subsurface-viewer",
"@webviz/well-completions-plot": "file:../typescript/packages/well-completions-plot",
"@webviz/well-log-viewer": "file:../typescript/packages/well-log-viewer",
Expand Down
36 changes: 21 additions & 15 deletions python/src/components/GroupTree/GroupTree.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import React from "react";
import PropTypes from "prop-types";

import {
DatedTreePropTypes,
EdgeMetadataPropTypes,
NodeMetadataPropTypes,
} from "@webviz/group-tree-plot";

const GroupTreeComponent = React.lazy(() =>
import(/* webpackChunkName: "webviz-group-tree" */ "@webviz/group-tree")
import(
/* webpackChunkName: "webviz-group-tree" */ "./components/GroupTreeComponent"
)
);

const GroupTree = (props) => {
const {
edge_options: edgeOptions,
node_options: nodeOptions,
...rest
} = props;
export const GroupTree = (props) => {
jorgenherje marked this conversation as resolved.
Show resolved Hide resolved
return (
<React.Suspense fallback={<div>Loading...</div>}>
<GroupTreeComponent
edgeOptions={edgeOptions}
nodeOptions={nodeOptions}
{...rest}
id={props.id}
data={props.data}
edgeMetadataList={props.edge_metadata_list}
nodeMetadataList={props.node_metadata_list}
/>
</React.Suspense>
);
Expand All @@ -29,15 +33,17 @@ GroupTree.propTypes = {
* components in an app.
*/
id: PropTypes.string.isRequired,

/**
* Array of JSON objects describing group tree data.
*/
data: PropTypes.arrayOf(PropTypes.object),
data: PropTypes.arrayOf(DatedTreePropTypes),

edge_options: PropTypes.arrayOf(PropTypes.object),
node_options: PropTypes.arrayOf(PropTypes.object),
/**
* Arrays of metadata. Used in drop down selectors and tree visualization.
*/
edge_metadata_list: EdgeMetadataPropTypes,
node_metadata_list: NodeMetadataPropTypes,
};

GroupTree.displayName = "GroupTree";

export default GroupTree;
69 changes: 69 additions & 0 deletions python/src/components/GroupTree/components/DataLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* eslint-disable react-hooks/exhaustive-deps */ // remove when ready to fix these.

import type { PropsWithChildren, ReactNode } from "react";
import React, { useMemo } from "react";
import { Provider as ReduxProvider } from "react-redux";
import { createReduxStore } from "../redux/store";
import type { UISettings } from "../redux/types";
import type {
DatedTree,
EdgeMetadata,
NodeMetadata,
} from "@webviz/group-tree-plot";

export type DateTreesIndices = {
treeIndex: number;
dateIndex: number;
};

interface DataProviderProps {
id: string;
data: DatedTree[];
edgeMetadataList: EdgeMetadata[];
nodeMetadataList: NodeMetadata[];
initialIndices: DateTreesIndices;
children: ReactNode;
}

export const DataContext = React.createContext<DatedTree[]>([]);

const DataProvider: React.FC<DataProviderProps> = (
props: PropsWithChildren<DataProviderProps>
) => {
const preloadedState = useMemo(() => {
// Use "initialIndices" from previous data if it refers to a valid date otherwise use first date.
const treeIdx = props.initialIndices.treeIndex;
const dateIdx = props.initialIndices.dateIndex;
const hasValidIndices =
props.data.length > treeIdx &&
props.data[treeIdx].dates.length > dateIdx;
const initialDateTime = hasValidIndices
? props.data[treeIdx].dates[dateIdx]
: props.data[0].dates[0];

const initialFlowRate = props.edgeMetadataList[0]?.key ?? "";
const initialNodeInfo = props.nodeMetadataList[0]?.key ?? "";

return {
id: props.id,
ui: {
currentDateTime: initialDateTime,
currentFlowRate: initialFlowRate,
currentNodeInfo: initialNodeInfo,
} as UISettings,
};
}, [props.id, props.data]); // Shallow compare does not detect updated data? Will useMemo actually help?

const store = useMemo(
() => createReduxStore(preloadedState),
[preloadedState]
);

return (
<DataContext.Provider value={props.data}>
<ReduxProvider store={store}>{props.children}</ReduxProvider>
</DataContext.Provider>
);
};

export default DataProvider;
72 changes: 72 additions & 0 deletions python/src/components/GroupTree/components/GroupTreeComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useCallback, useState } from "react";

import DataProvider, { DateTreesIndices } from "./DataLoader";
import GroupTreeViewer from "./GroupTreeViewer";
import { DatedTree, EdgeMetadata, NodeMetadata } from "@webviz/group-tree-plot";

//TODO schema check
export interface GroupTreeProps {
/**
* The ID of this component, used to identify dash components
* in callbacks. The ID needs to be unique across all of the
* components in an app.
*/
id: string;
/**
* Array of JSON objects describing group tree data.
*/
data: DatedTree[];

/**
* Arrays of metadata. Used in drop down selectors and tree visualization.
*/
edgeMetadataList: EdgeMetadata[];
nodeMetadataList: NodeMetadata[];
}

const GroupTreeComponent: React.FC<GroupTreeProps> = React.memo(
(props: GroupTreeProps) => {
const [indices, setIndices] = useState<DateTreesIndices>({
treeIndex: 0,
dateIndex: 0,
});

const currentDateTimeChangedCallBack = useCallback(
(currentDateTime: string) => {
const newTreeIndex = props.data.findIndex((e) => {
return e.dates.includes(currentDateTime);
});
const newDateIndex =
props.data[newTreeIndex].dates.indexOf(currentDateTime);

setIndices({
treeIndex: newTreeIndex,
dateIndex: newDateIndex,
});
},
[props.data]
);

return (
<DataProvider
id={props.id}
data={props.data}
edgeMetadataList={props.edgeMetadataList}
nodeMetadataList={props.nodeMetadataList}
initialIndices={indices}
>
<GroupTreeViewer
id={props.id}
edgeMetadataList={props.edgeMetadataList}
nodeMetadataList={props.nodeMetadataList}
currentDateTimeChangedCallBack={
currentDateTimeChangedCallBack
}
/>
</DataProvider>
);
}
);

GroupTreeComponent.displayName = "GroupTreeComponent";
export default GroupTreeComponent;
80 changes: 80 additions & 0 deletions python/src/components/GroupTree/components/GroupTreeViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* eslint-disable react-hooks/exhaustive-deps */ // remove when ready to fix these.

import { styled } from "@mui/material/styles";
import React, { useContext, useEffect } from "react";
import { useSelector } from "react-redux";
import type { GroupTreeState } from "../redux/store";
import { DataContext } from "./DataLoader";
import SettingsBar from "./Settings/SettingsBar";

import {
GroupTreePlot,
EdgeMetadata,
NodeMetadata,
} from "@webviz/group-tree-plot";

const PREFIX = "GroupTreeViewer";

const classes = {
root: `${PREFIX}-root`,
};

const Root = styled("div")(() => ({
[`&.${classes.root}`]: {
position: "relative",
display: "flex",
flex: 1,
flexDirection: "column",
height: "90%",
},
}));

interface GroupTreeViewerProps {
id: string;
edgeMetadataList: EdgeMetadata[];
nodeMetadataList: NodeMetadata[];
currentDateTimeChangedCallBack: (currentDateTime: string) => void;
}

const GroupTreeViewer: React.FC<GroupTreeViewerProps> = (
props: GroupTreeViewerProps
) => {
const data = useContext(DataContext);

const currentDateTime = useSelector(
(state: GroupTreeState) => state.ui.currentDateTime
);
const currentFlowRateKey = useSelector(
(state: GroupTreeState) => state.ui.currentFlowRate
);
const currentNodeKey = useSelector(
(state: GroupTreeState) => state.ui.currentNodeInfo
);

useEffect(() => {
if (typeof props.currentDateTimeChangedCallBack !== "undefined") {
props.currentDateTimeChangedCallBack(currentDateTime);
}
}, [currentDateTime]);

return (
<Root className={classes.root}>
<SettingsBar
edgeMetadataList={props.edgeMetadataList}
nodeMetadataList={props.nodeMetadataList}
/>
<GroupTreePlot
id={props.id}
datedTrees={data}
edgeMetadataList={props.edgeMetadataList}
nodeMetadataList={props.nodeMetadataList}
selectedEdgeKey={currentFlowRateKey}
selectedNodeKey={currentNodeKey}
selectedDateTime={currentDateTime}
/>
</Root>
);
};

GroupTreeViewer.displayName = "GroupTreeViewer";
export default GroupTreeViewer;
Loading