From ef07441041f20f360393237ea2e1484355451260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= <82032112+jorgenherje@users.noreply.github.com> Date: Tue, 12 Dec 2023 20:21:49 +0100 Subject: [PATCH] feat: Split GroupTree into GroupTreePlot-component and settings (#1794) Split previous `/package/group-tree` into a view-component, `/package/group-tree-plot`, which is independent of `redux` and `mui`. The old `GroupTree`-component placed in `python/src/components`, for usage in Dash, now has a lot of the code from the old `/package/group-tree` Thereby the new `group-tree-plot` can be used directly in Webviz NextGen. Removed package: `package/group-tree` New package: `package/group-tree-plot` ----- Closes: https://github.com/equinor/webviz/issues/461 --- python/package-lock.json | 39 +- python/package.json | 2 +- python/src/components/GroupTree/GroupTree.jsx | 34 +- .../GroupTree/components/DataLoader.tsx | 69 +++ .../components/GroupTreeComponent.tsx | 72 +++ .../GroupTree/components/GroupTreeViewer.tsx | 80 +++ .../components/Settings/DateTimeSlider.tsx | 7 +- .../components/Settings/FlowRateSelector.tsx | 16 +- .../components/Settings/NodeInfoSelector.tsx | 18 +- .../components/Settings/SettingsBar.tsx | 20 +- .../components/Settings/date_time_slider.css | 30 ++ python/src/components/GroupTree/index.ts | 2 +- .../components/GroupTree}/redux/actions.ts | 0 .../components/GroupTree}/redux/reducer.ts | 0 .../src/components/GroupTree}/redux/store.ts | 0 .../src/components/GroupTree/redux/types.ts | 5 + python/src/index.ts | 2 +- .../py_expression_eval.py | 1 + typescript/package-lock.json | 20 +- .../example-data/dated-trees.ts | 166 ++++++ .../package.json | 17 +- .../project.json | 0 .../GroupTreeAssembler/groupTreeAssembler.js} | 171 ++++-- .../src/GroupTreeAssembler/group_tree.css | 59 +++ .../group-tree-plot/src/GroupTreePlot.tsx | 87 ++++ .../packages/group-tree-plot/src/index.ts | 18 + .../src/storybook/GroupTreePlot.stories.tsx | 69 +++ .../packages/group-tree-plot/src/types.ts | 85 +++ .../tsconfig.json | 8 +- typescript/packages/group-tree/CHANGELOG.md | 55 -- typescript/packages/group-tree/jest.config.js | 7 - .../group-tree/src/GroupTree.test.tsx | 56 -- .../packages/group-tree/src/GroupTree.tsx | 40 -- .../src/GroupTree_performance.test.tsx | 80 --- .../src/__snapshots__/GroupTree.test.tsx.snap | 492 ------------------ .../group-tree/src/components/DataLoader.tsx | 65 --- .../components/GroupTreeComponent.test.tsx | 57 -- .../src/components/GroupTreeComponent.tsx | 65 --- .../src/components/GroupTreeViewer.test.tsx | 56 -- .../src/components/GroupTreeViewer.tsx | 103 ---- .../src/components/Plot/dynamic_tree.css | 201 ------- .../Settings/DateTimeSlider.test.tsx | 24 - .../Settings/FlowRateSelector.test.tsx | 42 -- .../Settings/NodeInfoSelector.test.tsx | 39 -- .../components/Settings/SettingsBar.test.tsx | 35 -- .../DateTimeSlider.test.tsx.snap | 76 --- .../FlowRateSelector.test.tsx.snap | 134 ----- .../NodeInfoSelector.test.tsx.snap | 119 ----- .../__snapshots__/SettingsBar.test.tsx.snap | 310 ----------- .../GroupTreeComponent.test.tsx.snap | 492 ------------------ .../GroupTreeViewer.test.tsx.snap | 492 ------------------ typescript/packages/group-tree/src/index.ts | 2 - .../packages/group-tree/src/redux/types.ts | 26 - .../storybook/GroupTreeComponent.stories.tsx | 32 -- .../components/DateTimeSlider.stories.tsx | 31 -- .../components/FlowRateSelector.stories.tsx | 40 -- .../components/GroupTreeViewer.stories.tsx | 50 -- .../components/SettingsBar.stories.tsx | 49 -- .../group-tree/src/test/TestWrapper.tsx | 24 - .../group-tree/src/test/performanceMetrics.ts | 20 - .../group-tree/src/test/testReduxState.ts | 10 - 61 files changed, 958 insertions(+), 3463 deletions(-) create mode 100644 python/src/components/GroupTree/components/DataLoader.tsx create mode 100644 python/src/components/GroupTree/components/GroupTreeComponent.tsx create mode 100644 python/src/components/GroupTree/components/GroupTreeViewer.tsx rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/components/Settings/DateTimeSlider.tsx (94%) rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/components/Settings/FlowRateSelector.tsx (77%) rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/components/Settings/NodeInfoSelector.tsx (73%) rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/components/Settings/SettingsBar.tsx (66%) create mode 100644 python/src/components/GroupTree/components/Settings/date_time_slider.css rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/redux/actions.ts (100%) rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/redux/reducer.ts (100%) rename {typescript/packages/group-tree/src => python/src/components/GroupTree}/redux/store.ts (100%) create mode 100644 python/src/components/GroupTree/redux/types.ts create mode 100644 typescript/packages/group-tree-plot/example-data/dated-trees.ts rename typescript/packages/{group-tree => group-tree-plot}/package.json (56%) rename typescript/packages/{group-tree => group-tree-plot}/project.json (100%) rename typescript/packages/{group-tree/src/components/Plot/group_tree.js => group-tree-plot/src/GroupTreeAssembler/groupTreeAssembler.js} (78%) create mode 100644 typescript/packages/group-tree-plot/src/GroupTreeAssembler/group_tree.css create mode 100644 typescript/packages/group-tree-plot/src/GroupTreePlot.tsx create mode 100644 typescript/packages/group-tree-plot/src/index.ts create mode 100644 typescript/packages/group-tree-plot/src/storybook/GroupTreePlot.stories.tsx create mode 100644 typescript/packages/group-tree-plot/src/types.ts rename typescript/packages/{group-tree => group-tree-plot}/tsconfig.json (51%) delete mode 100644 typescript/packages/group-tree/CHANGELOG.md delete mode 100644 typescript/packages/group-tree/jest.config.js delete mode 100644 typescript/packages/group-tree/src/GroupTree.test.tsx delete mode 100644 typescript/packages/group-tree/src/GroupTree.tsx delete mode 100644 typescript/packages/group-tree/src/GroupTree_performance.test.tsx delete mode 100644 typescript/packages/group-tree/src/__snapshots__/GroupTree.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/DataLoader.tsx delete mode 100644 typescript/packages/group-tree/src/components/GroupTreeComponent.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/GroupTreeComponent.tsx delete mode 100644 typescript/packages/group-tree/src/components/GroupTreeViewer.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/GroupTreeViewer.tsx delete mode 100644 typescript/packages/group-tree/src/components/Plot/dynamic_tree.css delete mode 100644 typescript/packages/group-tree/src/components/Settings/DateTimeSlider.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/Settings/FlowRateSelector.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/Settings/SettingsBar.test.tsx delete mode 100644 typescript/packages/group-tree/src/components/Settings/__snapshots__/DateTimeSlider.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/Settings/__snapshots__/FlowRateSelector.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/Settings/__snapshots__/NodeInfoSelector.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/Settings/__snapshots__/SettingsBar.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/__snapshots__/GroupTreeComponent.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/components/__snapshots__/GroupTreeViewer.test.tsx.snap delete mode 100644 typescript/packages/group-tree/src/index.ts delete mode 100644 typescript/packages/group-tree/src/redux/types.ts delete mode 100644 typescript/packages/group-tree/src/storybook/GroupTreeComponent.stories.tsx delete mode 100644 typescript/packages/group-tree/src/storybook/components/DateTimeSlider.stories.tsx delete mode 100644 typescript/packages/group-tree/src/storybook/components/FlowRateSelector.stories.tsx delete mode 100644 typescript/packages/group-tree/src/storybook/components/GroupTreeViewer.stories.tsx delete mode 100644 typescript/packages/group-tree/src/storybook/components/SettingsBar.stories.tsx delete mode 100644 typescript/packages/group-tree/src/test/TestWrapper.tsx delete mode 100644 typescript/packages/group-tree/src/test/performanceMetrics.ts delete mode 100644 typescript/packages/group-tree/src/test/testReduxState.ts diff --git a/python/package-lock.json b/python/package-lock.json index 7f79217ac..58061e237 100644 --- a/python/package-lock.json +++ b/python/package-lock.json @@ -17,7 +17,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", @@ -72,33 +72,26 @@ "../typescript/packages/dash-components/dist": { "extraneous": true }, - "../typescript/packages/group-tree": { - "name": "@webviz/group-tree", - "version": "1.0.1", + "../typescript/packages/group-tree-plot": { + "name": "@webviz/group-tree-plot", + "version": "0.0.1", "license": "MPL-2.0", "dependencies": { - "@equinor/eds-core-react": "^0.33.0", - "@reduxjs/toolkit": "^1.7.2", "d3": "^7.8.2", - "lodash": "^4.17.21", - "react-redux": "^8.1.1" + "lodash": "^4.17.21" }, "peerDependencies": { - "@mui/material": "^5.11", "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, - "../typescript/packages/group-tree/dist": { - "extraneous": true - }, "../typescript/packages/subsurface-viewer": { "name": "@webviz/subsurface-viewer", - "version": "0.3.3", + "version": "0.9.0", "license": "MPL-2.0", "dependencies": { - "@deck.gl/core": "^8.8.25", - "@emerson-eps/color-tables": "^0.4.61", + "@deck.gl/core": "^8.9.32", + "@emerson-eps/color-tables": "^0.4.71", "@equinor/eds-core-react": "^0.33.0", "@equinor/eds-icons": "^0.19.1", "@nebula.gl/layers": "^1.0.4", @@ -111,7 +104,7 @@ "d3": "^7.8.2", "d3-color": "^3.1.0", "d3-format": "^3.1.0", - "deck.gl": "^8.9.31", + "deck.gl": "^8.9.32", "gl-matrix": "^3.4.3", "lodash": "^4.17.21", "mathjs": "^9.4.2", @@ -129,7 +122,7 @@ }, "../typescript/packages/well-completions-plot": { "name": "@webviz/well-completions-plot", - "version": "1.0.1", + "version": "1.0.7", "license": "MPL-2.0", "dependencies": { "react-resize-detector": "^9.1.0", @@ -141,11 +134,11 @@ }, "../typescript/packages/well-log-viewer": { "name": "@webviz/well-log-viewer", - "version": "1.1.1", + "version": "1.1.8", "license": "MPL-2.0", "dependencies": { - "@emerson-eps/color-tables": "^0.4.61", - "@equinor/videx-wellog": "^0.8.0", + "@emerson-eps/color-tables": "^0.4.71", + "@equinor/videx-wellog": "^0.8.1", "@webviz/wsc-common": "*", "convert-units": "^2.3.4", "d3": "^7.8.2" @@ -161,7 +154,7 @@ }, "../typescript/packages/wsc-common": { "name": "@webviz/wsc-common", - "version": "0.2.1", + "version": "0.2.7", "license": "MPL-2.0", "dependencies": { "ajv": "^7.2.1" @@ -3291,8 +3284,8 @@ "object-assign": "^4.1.1" } }, - "node_modules/@webviz/group-tree": { - "resolved": "../typescript/packages/group-tree", + "node_modules/@webviz/group-tree-plot": { + "resolved": "../typescript/packages/group-tree-plot", "link": true }, "node_modules/@webviz/subsurface-viewer": { diff --git a/python/package.json b/python/package.json index 9f880672d..a0977e64a 100644 --- a/python/package.json +++ b/python/package.json @@ -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", diff --git a/python/src/components/GroupTree/GroupTree.jsx b/python/src/components/GroupTree/GroupTree.jsx index 4a9d70a84..2eec2df48 100644 --- a/python/src/components/GroupTree/GroupTree.jsx +++ b/python/src/components/GroupTree/GroupTree.jsx @@ -1,21 +1,25 @@ 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) => { + const { edge_metadata_list, node_metadata_list, ...rest } = props; return ( Loading...}> @@ -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; diff --git a/python/src/components/GroupTree/components/DataLoader.tsx b/python/src/components/GroupTree/components/DataLoader.tsx new file mode 100644 index 000000000..838ddb62e --- /dev/null +++ b/python/src/components/GroupTree/components/DataLoader.tsx @@ -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([]); + +const DataProvider: React.FC = ( + props: PropsWithChildren +) => { + 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 ( + + {props.children} + + ); +}; + +export default DataProvider; diff --git a/python/src/components/GroupTree/components/GroupTreeComponent.tsx b/python/src/components/GroupTree/components/GroupTreeComponent.tsx new file mode 100644 index 000000000..6556f5833 --- /dev/null +++ b/python/src/components/GroupTree/components/GroupTreeComponent.tsx @@ -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 = React.memo( + (props: GroupTreeProps) => { + const [indices, setIndices] = useState({ + 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 ( + + + + ); + } +); + +GroupTreeComponent.displayName = "GroupTreeComponent"; +export default GroupTreeComponent; diff --git a/python/src/components/GroupTree/components/GroupTreeViewer.tsx b/python/src/components/GroupTree/components/GroupTreeViewer.tsx new file mode 100644 index 000000000..12b7e9442 --- /dev/null +++ b/python/src/components/GroupTree/components/GroupTreeViewer.tsx @@ -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 = ( + 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 ( + + + + + ); +}; + +GroupTreeViewer.displayName = "GroupTreeViewer"; +export default GroupTreeViewer; diff --git a/typescript/packages/group-tree/src/components/Settings/DateTimeSlider.tsx b/python/src/components/GroupTree/components/Settings/DateTimeSlider.tsx similarity index 94% rename from typescript/packages/group-tree/src/components/Settings/DateTimeSlider.tsx rename to python/src/components/GroupTree/components/Settings/DateTimeSlider.tsx index 9e04fa805..fffa4574c 100644 --- a/typescript/packages/group-tree/src/components/Settings/DateTimeSlider.tsx +++ b/python/src/components/GroupTree/components/Settings/DateTimeSlider.tsx @@ -4,9 +4,12 @@ import React, { useCallback, useContext, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { updateCurrentDateTime } from "../../redux/actions"; import type { GroupTreeState } from "../../redux/store"; -import type { Data, DatedTree } from "../../redux/types"; import { DataContext } from "../DataLoader"; +import { DatedTree } from "@webviz/group-tree-plot"; + +import "./date_time_slider.css"; + const classes = { root: "DateTimeSlider-root", }; @@ -32,7 +35,7 @@ const EdsSlider = styled(Slider)(() => ({ })); const DateTimeSlider: React.FC = React.memo(() => { - const data: Data = useContext(DataContext); + const data: DatedTree[] = useContext(DataContext); // Redux const dispatch = useDispatch(); diff --git a/typescript/packages/group-tree/src/components/Settings/FlowRateSelector.tsx b/python/src/components/GroupTree/components/Settings/FlowRateSelector.tsx similarity index 77% rename from typescript/packages/group-tree/src/components/Settings/FlowRateSelector.tsx rename to python/src/components/GroupTree/components/Settings/FlowRateSelector.tsx index 8c8d170d4..4bec54b3a 100644 --- a/typescript/packages/group-tree/src/components/Settings/FlowRateSelector.tsx +++ b/python/src/components/GroupTree/components/Settings/FlowRateSelector.tsx @@ -4,7 +4,7 @@ import React, { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; import { updateCurrentFlowRate } from "../../redux/actions"; import type { GroupTreeState } from "../../redux/store"; -import type { DataInfos, DataInfo } from "../../redux/types"; +import { EdgeMetadata } from "@webviz/group-tree-plot"; const PREFIX = "FlowRateSelector"; @@ -19,12 +19,12 @@ const StyledNativeSelect = styled(NativeSelect)(({ theme }) => ({ }, })); -interface Props { - edge_options: DataInfos; +interface FlowRateSelectorProps { + edgeMetadataList: EdgeMetadata[]; } -const FlowRateSelector: React.FC = React.memo( - ({ edge_options }: Props) => { +const FlowRateSelector: React.FC = React.memo( + (props: FlowRateSelectorProps) => { // Redux const dispatch = useDispatch(); const currentFlowRate = useSelector( @@ -46,9 +46,9 @@ const FlowRateSelector: React.FC = React.memo( value={currentFlowRate} onChange={handleSelectedItemChange} > - {edge_options.map((key: DataInfo) => ( - ))} diff --git a/typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.tsx b/python/src/components/GroupTree/components/Settings/NodeInfoSelector.tsx similarity index 73% rename from typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.tsx rename to python/src/components/GroupTree/components/Settings/NodeInfoSelector.tsx index 4837ded65..ec07a697b 100644 --- a/typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.tsx +++ b/python/src/components/GroupTree/components/Settings/NodeInfoSelector.tsx @@ -4,7 +4,7 @@ import React, { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; import { updateCurrentNodeInfo } from "../../redux/actions"; import type { GroupTreeState } from "../../redux/store"; -import type { DataInfos, DataInfo } from "../../redux/types"; +import { NodeMetadata } from "@webviz/group-tree-plot"; const PREFIX = "NodeInfoSelector"; @@ -19,12 +19,12 @@ const StyledNativeSelect = styled(NativeSelect)(({ theme }) => ({ }, })); -interface Props { - node_options: DataInfos; +interface NodeInfoSelectorProps { + nodeMetadataList: NodeMetadata[]; } -const NodeInfoSelector: React.FC = React.memo( - ({ node_options }: Props) => { +const NodeInfoSelector: React.FC = React.memo( + (props: NodeInfoSelectorProps) => { // Redux const dispatch = useDispatch(); const currentNodeInfo = useSelector( @@ -32,7 +32,7 @@ const NodeInfoSelector: React.FC = React.memo( ); // handlers const handleSelectedItemChange = useCallback( - (event: { target: { value: unknown } }) => { + (event: React.ChangeEvent) => { dispatch(updateCurrentNodeInfo(event.target.value as string)); }, [dispatch] @@ -46,9 +46,9 @@ const NodeInfoSelector: React.FC = React.memo( value={currentNodeInfo} onChange={handleSelectedItemChange} > - {node_options.map((key: DataInfo) => ( - ))} diff --git a/typescript/packages/group-tree/src/components/Settings/SettingsBar.tsx b/python/src/components/GroupTree/components/Settings/SettingsBar.tsx similarity index 66% rename from typescript/packages/group-tree/src/components/Settings/SettingsBar.tsx rename to python/src/components/GroupTree/components/Settings/SettingsBar.tsx index 49e7c7d7c..fdfa814e6 100644 --- a/typescript/packages/group-tree/src/components/Settings/SettingsBar.tsx +++ b/python/src/components/GroupTree/components/Settings/SettingsBar.tsx @@ -4,7 +4,7 @@ import React from "react"; import DateTimeSlider from "./DateTimeSlider"; import FlowRateSelector from "./FlowRateSelector"; import NodeInfoSelector from "./NodeInfoSelector"; -import type { DataInfos } from "../../redux/types"; +import { EdgeMetadata, NodeMetadata } from "@webviz/group-tree-plot"; const PREFIX = "SettingsBar"; @@ -25,18 +25,22 @@ const StyledTopBar = styled(TopBar)(() => ({ }, })); -interface Props { - edge_options: DataInfos; - node_options: DataInfos; +interface SettingsBarProps { + edgeMetadataList: EdgeMetadata[]; + nodeMetadataList: NodeMetadata[]; } -const SettingsBar: React.FC = React.memo( - ({ edge_options, node_options }: Props) => { +const SettingsBar: React.FC = React.memo( + (props: SettingsBarProps) => { return ( - - + + diff --git a/python/src/components/GroupTree/components/Settings/date_time_slider.css b/python/src/components/GroupTree/components/Settings/date_time_slider.css new file mode 100644 index 000000000..05c5d65e2 --- /dev/null +++ b/python/src/components/GroupTree/components/Settings/date_time_slider.css @@ -0,0 +1,30 @@ +/* +This css is to override default slider css styling for the date time slider +*/ + +.slider, +.slider-inset, +.slider-overlay { + stroke-linecap: round; +} + +.slider { + stroke-width: 8px; +} + +.slider-inset { + stroke: #b20276; + stroke-width: 8px; +} + +.slider-overlay { + pointer-events: stroke; + cursor: pointer; +} + +.handle { + fill: #fff; + stroke: #b20276; + stroke-opacity: 0.5; + stroke-width: 1.25px; +} diff --git a/python/src/components/GroupTree/index.ts b/python/src/components/GroupTree/index.ts index 5e582260b..e32e28507 100644 --- a/python/src/components/GroupTree/index.ts +++ b/python/src/components/GroupTree/index.ts @@ -1 +1 @@ -export { default } from "./GroupTree"; +export { GroupTree } from "./GroupTree"; diff --git a/typescript/packages/group-tree/src/redux/actions.ts b/python/src/components/GroupTree/redux/actions.ts similarity index 100% rename from typescript/packages/group-tree/src/redux/actions.ts rename to python/src/components/GroupTree/redux/actions.ts diff --git a/typescript/packages/group-tree/src/redux/reducer.ts b/python/src/components/GroupTree/redux/reducer.ts similarity index 100% rename from typescript/packages/group-tree/src/redux/reducer.ts rename to python/src/components/GroupTree/redux/reducer.ts diff --git a/typescript/packages/group-tree/src/redux/store.ts b/python/src/components/GroupTree/redux/store.ts similarity index 100% rename from typescript/packages/group-tree/src/redux/store.ts rename to python/src/components/GroupTree/redux/store.ts diff --git a/python/src/components/GroupTree/redux/types.ts b/python/src/components/GroupTree/redux/types.ts new file mode 100644 index 000000000..77a1a8cfe --- /dev/null +++ b/python/src/components/GroupTree/redux/types.ts @@ -0,0 +1,5 @@ +export interface UISettings { + currentDateTime: string; + currentFlowRate: string; + currentNodeInfo: string; +} diff --git a/python/src/index.ts b/python/src/index.ts index 95a93372e..0fe54b80a 100644 --- a/python/src/index.ts +++ b/python/src/index.ts @@ -1,6 +1,6 @@ import DashSubsurfaceViewer from "./components/DashSubsurfaceViewer"; import SubsurfaceViewer from "./components/SubsurfaceViewer"; -import GroupTree from "./components/GroupTree"; +import { GroupTree } from "./components/GroupTree"; import HistoryMatch from "./components/HistoryMatch"; import LeafletMap from "./components/LeafletMap"; import Map from "./components/Map"; diff --git a/python/webviz_subsurface_components/py_expression_eval.py b/python/webviz_subsurface_components/py_expression_eval.py index 85be28825..8bbd29042 100644 --- a/python/webviz_subsurface_components/py_expression_eval.py +++ b/python/webviz_subsurface_components/py_expression_eval.py @@ -33,6 +33,7 @@ Based on js-expression-eval, by Matthew Crumley https://github.com/silentmatt/js-expression-eval """ + import re import numpy as np diff --git a/typescript/package-lock.json b/typescript/package-lock.json index c181e4c38..e66f3a952 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -13605,8 +13605,8 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webviz/group-tree": { - "resolved": "packages/group-tree", + "node_modules/@webviz/group-tree-plot": { + "resolved": "packages/group-tree-plot", "link": true }, "node_modules/@webviz/subsurface-viewer": { @@ -40284,7 +40284,8 @@ }, "packages/group-tree": { "name": "@webviz/group-tree", - "version": "1.0.6", + "version": "1.0.5", + "extraneous": true, "license": "MPL-2.0", "dependencies": { "@equinor/eds-core-react": "^0.33.0", @@ -40299,6 +40300,19 @@ "react-dom": "^17 || ^18" } }, + "packages/group-tree-plot": { + "name": "@webviz/group-tree-plot", + "version": "0.0.1", + "license": "MPL-2.0", + "dependencies": { + "d3": "^7.8.2", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "react": "^17 || ^18", + "react-dom": "^17 || ^18" + } + }, "packages/subsurface-viewer": { "name": "@webviz/subsurface-viewer", "version": "0.8.1", diff --git a/typescript/packages/group-tree-plot/example-data/dated-trees.ts b/typescript/packages/group-tree-plot/example-data/dated-trees.ts new file mode 100644 index 000000000..ae329232f --- /dev/null +++ b/typescript/packages/group-tree-plot/example-data/dated-trees.ts @@ -0,0 +1,166 @@ +import { DatedTree } from "../src/types"; + +/** + * This is the dates present in the dates trees example data. + */ +export const exampleDates: string[] = [ + "2018-02-01", + "2018-03-01", + "2019-02-01", + "2019-03-01", +]; + +/** + * This is example data based on the Group Tree data in `group-tree.json`-file found in the `example-data`-folder. + * + * This is converted to .ts file to obtain type safety. + */ + +const firstDatedTree: DatedTree = { + dates: ["2018-02-01", "2018-03-01"], + tree: { + node_label: "TRE_1", + node_type: "Group", + node_data: { + pressure: [5, 10], + }, + edge_label: "VFP10", + edge_data: { + waterrate: [10, 10], + oilrate: [10, 10], + gasrate: [10, 10], + waterinjrate: [10, 10], + gasinjrate: [10, 10], + }, + children: [ + { + node_label: "TRE_1_1", + node_type: "Well", + node_data: { + pressure: [20, 30], + bhp: [11, 10], + wmctl: [12, 10], + }, + edge_label: "VFP11", + edge_data: { + waterrate: [20, 30], + oilrate: [30, 40], + gasrate: [40, 50], + waterinjrate: [50, 60], + gasinjrate: [60, 70], + }, + children: undefined, + }, + { + node_label: "TRE_1_2", + node_type: "Well", + node_data: { + pressure: [22, 30], + wmctl: [10, 10], + }, + edge_label: "VFP12", + edge_data: { + waterrate: [25, 35], + oilrate: [35, 45], + gasrate: [45, 55], + waterinjrate: [55, 65], + gasinjrate: [65, 75], + }, + children: undefined, + }, + ], + }, +}; + +const secondDatedTree: DatedTree = { + dates: ["2019-02-01", "2019-03-01"], + tree: { + node_label: "TRE_1", + node_type: "Group", + node_data: { + pressure: [5, 10], + }, + edge_label: "VFP10", + edge_data: { + waterrate: [10, 10], + oilrate: [10, 10], + gasrate: [10, 10], + waterinjrate: [10, 10], + gasinjrate: [10, 10], + }, + children: [ + { + node_label: "TRE_1_1", + node_type: "Well", + node_data: { + pressure: [20, 30], + bhp: [10, 10], + wmctl: [10, 10], + }, + edge_label: "VFP11", + edge_data: { + waterrate: [20, 30], + oilrate: [30, 40], + gasrate: [40, 50], + waterinjrate: [50, 60], + gasinjrate: [60, 70], + }, + children: [ + { + node_label: "TRE_1_1_1", + node_type: "Well", + node_data: { + pressure: [20, 30], + bhp: [10, 10], + wmctl: [10, 10], + }, + edge_label: "VFP12", + edge_data: { + waterrate: [20, 30], + oilrate: [30, 40], + gasrate: [40, 50], + waterinjrate: [50, 60], + gasinjrate: [60, 70], + }, + }, + { + node_label: "TRE_1_1_2", + node_type: "Well", + node_data: { + pressure: [20, 30], + bhp: [10, 10], + wmctl: [10, 10], + }, + edge_label: "VFP13", + edge_data: { + waterrate: [20, 30], + oilrate: [30, 40], + gasrate: [40, 50], + waterinjrate: [50, 60], + gasinjrate: [60, 70], + }, + }, + ], + }, + { + node_label: "TRE_1_2", + node_type: "Well", + node_data: { + pressure: [20, 30], + bhp: [10, 10], + wmctl: [10, 10], + }, + edge_label: "VFP14", + edge_data: { + waterrate: [20, 30], + oilrate: [30, 40], + gasrate: [40, 50], + waterinjrate: [50, 60], + gasinjrate: [60, 70], + }, + }, + ], + }, +}; + +export const exampleDatedTrees: DatedTree[] = [firstDatedTree, secondDatedTree]; diff --git a/typescript/packages/group-tree/package.json b/typescript/packages/group-tree-plot/package.json similarity index 56% rename from typescript/packages/group-tree/package.json rename to typescript/packages/group-tree-plot/package.json index 6abb4a959..4f5357ba5 100644 --- a/typescript/packages/group-tree/package.json +++ b/typescript/packages/group-tree-plot/package.json @@ -1,34 +1,25 @@ { - "name": "@webviz/group-tree", - "version": "1.0.7", + "name": "@webviz/group-tree-plot", + "version": "0.0.1", "description": "", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ - "dist" + "/dist" ], "scripts": { "transpile": "tsc --project ./tsconfig.json", "copy-files": "copyfiles --up 1 \"src/**/*.css\" dist/", "build": "git clean -xdff dist && npm run transpile && npm run copy-files", - "test_perf": "jest _performance", - "test_correctness": "jest --coverage --testPathIgnorePatterns='_performance'", - "test": "jest --coverage", - "test:update": "npm test -- --u", - "test:watch": "npm test -- --watch", "doc": "git clean -xdff docs && typedoc src" }, "author": "Equinor ", "license": "MPL-2.0", "dependencies": { - "@equinor/eds-core-react": "^0.33.0", - "@reduxjs/toolkit": "^1.7.2", "d3": "^7.8.2", - "lodash": "^4.17.21", - "react-redux": "^8.1.1" + "lodash": "^4.17.21" }, "peerDependencies": { - "@mui/material": "^5.11", "react": "^17 || ^18", "react-dom": "^17 || ^18" }, diff --git a/typescript/packages/group-tree/project.json b/typescript/packages/group-tree-plot/project.json similarity index 100% rename from typescript/packages/group-tree/project.json rename to typescript/packages/group-tree-plot/project.json diff --git a/typescript/packages/group-tree/src/components/Plot/group_tree.js b/typescript/packages/group-tree-plot/src/GroupTreeAssembler/groupTreeAssembler.js similarity index 78% rename from typescript/packages/group-tree/src/components/Plot/group_tree.js rename to typescript/packages/group-tree-plot/src/GroupTreeAssembler/groupTreeAssembler.js index 837e3237b..3d806cf6c 100644 --- a/typescript/packages/group-tree/src/components/Plot/group_tree.js +++ b/typescript/packages/group-tree-plot/src/GroupTreeAssembler/groupTreeAssembler.js @@ -5,6 +5,9 @@ * 9 july 2021: refactored to use new format. */ import * as d3 from "d3"; +import "./group_tree.css"; +import { cloneDeep } from "lodash"; + /* eslint camelcase: "off" */ /* eslint array-callback-return: "off" */ /* eslint no-return-assign: "off" */ @@ -13,46 +16,54 @@ import * as d3 from "d3"; /* Fix this lint when rewriting the whole file */ /** - * Group tree visualization. Creates an _svg, and appends to the assigned element. - * Draws the tree provided as tree_data - - * @constructor + * Class to assemble Group tree visualization. Creates an _svg, and appends to the + * assigned HTML element. Draws the tree provided in datedTrees with the current flow rate, + * node info and date time. + * + * Provides methods to update selected date time, and change flow rate and node info. */ -export default class GroupTree { +export default class GroupTreeAssembler { /** * - * @param dom_element_id - * @param {group-tree-data} tree_data - * @param defaultFlowrate + * @param dom_element_id - id of the HTML element to append the _svg to + * @param datedTrees - List of dated tree data structure containing the trees to visualize + * @param initialFlowRate - key identifying the initial selected flow rate for the tree edges + * @param initialNodeInfo - key identifying the initial selected node info for the tree nodes + * @param currentDateTime - the initial/current date time + * @param edgeMetadataList - List of metadata for the edge keys in the tree data structure + * @param nodeMetadataList - List of metadata for the node keys in the tree data structure */ constructor( dom_element_id, - tree_data, - defaultFlowrate, - defaultNodeInfo, + datedTrees, + initialFlowRate, + initialNodeInfo, currentDateTime, - edge_options, - node_options + edgeMetadataList, + nodeMetadataList ) { + // Cloned as it is mutated within class + let clonedDatedTrees = cloneDeep(datedTrees); + // Add "#" if missing. if (dom_element_id.charAt(0) !== "#") { dom_element_id = "#" + dom_element_id; } // Map from property to [label/name, unit] - const options = [...edge_options, ...node_options]; + const metadataList = [...edgeMetadataList, ...nodeMetadataList]; this._propertyToLabelMap = new Map(); - options.forEach((key) => { - this._propertyToLabelMap.set(key.name, [ - key.label ?? "", - key.unit ?? "", + metadataList.forEach((elm) => { + this._propertyToLabelMap.set(elm.key, [ + elm.label ?? "", + elm.unit ?? "", ]); }); // Represent possible empty data by single empty node. - if (tree_data.length === 0) { + if (clonedDatedTrees.length === 0) { currentDateTime = ""; - tree_data = [ + clonedDatedTrees = [ { dates: [currentDateTime], tree: { @@ -65,15 +76,15 @@ export default class GroupTree { ]; } - this._currentFlowrate = defaultFlowrate; - this._currentNodeInfo = defaultNodeInfo; + this._currentFlowRate = initialFlowRate; + this._currentNodeInfo = initialNodeInfo; this._currentDateTime = currentDateTime; this._transitionTime = 200; const tree_values = {}; - tree_data.map((datedTree) => { + clonedDatedTrees.map((datedTree) => { let tree = datedTree.tree; d3.hierarchy(tree, (d) => d.children).each((node) => { // edge_data @@ -95,9 +106,6 @@ export default class GroupTree { .range([2, 100]); }); - const select = d3.select(dom_element_id); - this._width = select.node().getBoundingClientRect().width; - const margin = { top: 10, right: 90, @@ -105,8 +113,16 @@ export default class GroupTree { left: 90, }; - const height = 700 - margin.top - margin.bottom; - this._width = this._width - margin.left - margin.right; + const select = d3.select(dom_element_id); + + // Svg bounding client rect + this._rectWidth = select.node().getBoundingClientRect().width; + this._rectHeight = 700; + this._rectLeftMargin = -margin.left; + this._rectTopMargin = -margin.top; + + const treeHeight = this._rectHeight - margin.top - margin.bottom; + this._treeWidth = this._rectWidth - margin.left - margin.right; // Clear possible existing svg's. d3.select(dom_element_id).selectAll("svg").remove(); @@ -114,16 +130,19 @@ export default class GroupTree { this._svg = d3 .select(dom_element_id) .append("svg") - .attr("width", this._width + margin.right + margin.left) - .attr("height", height + margin.top + margin.bottom) + .attr("width", this._treeWidth + margin.right + margin.left) + .attr("height", treeHeight + margin.top + margin.bottom) .append("g") .attr("transform", `translate(${margin.left},${margin.top})`); this._textpaths = this._svg.append("g"); - this._renderTree = d3.tree().size([height, this._width]); + this._renderTree = d3.tree().size([treeHeight, this._treeWidth]); - this._data = GroupTree.initHierarchies(tree_data, height); + this._data = GroupTreeAssembler.initHierarchies( + clonedDatedTrees, + treeHeight + ); this._currentTree = {}; @@ -166,16 +185,26 @@ export default class GroupTree { * @param flowrate - key identifying the flowrate of the incoming edge */ set flowrate(flowrate) { - this._currentFlowrate = flowrate; + this._currentFlowRate = flowrate; const current_tree_index = this._data.findIndex((e) => { return e.dates.includes(this._currentDateTime); }); + if (current_tree_index === -1) { + this._svg.selectAll("path.link").remove(); + return; + } + const date_index = this._data[current_tree_index].dates.indexOf( this._currentDateTime ); + if (date_index === -1) { + this._svg.selectAll("path.link").remove(); + return; + } + this._svg .selectAll("path.link") .transition() @@ -198,7 +227,7 @@ export default class GroupTree { } get flowrate() { - return this._currentFlowrate; + return this._currentFlowRate; } set nodeinfo(nodeinfo) { @@ -208,10 +237,20 @@ export default class GroupTree { return e.dates.includes(this._currentDateTime); }); + if (current_tree_index === -1) { + this._svg.selectAll("path.link").remove(); + return; + } + const date_index = this._data[current_tree_index].dates.indexOf( this._currentDateTime ); + if (date_index === -1) { + this._svg.selectAll("path.link").remove(); + return; + } + this._svg .selectAll(".grouptree__pressurelabel") .text( @@ -248,15 +287,21 @@ export default class GroupTree { update(newDateTime) { const self = this; - self._currentDateTime = newDateTime; - const new_tree_index = self._data.findIndex((e) => { return e.dates.includes(newDateTime); }); const root = self._data[new_tree_index]; - const date_index = root.dates.indexOf(self._currentDateTime); + const date_index = root?.dates.indexOf(newDateTime) ?? -1; + + // Invalid date gives invalid indices + const hasInvalidDate = + !root || date_index === -1 || new_tree_index === -1; + + if (hasInvalidDate) { + self._currentDateTime = newDateTime; + } /** * Assigns y coordinates to all tree nodes in the rendered tree. @@ -513,7 +558,7 @@ export default class GroupTree { /** * Draw new edges, and update existing ones. * - * @param edges -list of nodes in a tree + * @param edges -list of edges in a tree * @param flowrate - key identifying the flowrate of the incoming edge */ function updateEdges(edges, flowrate) { @@ -586,7 +631,7 @@ export default class GroupTree { /** * Add new and update existing texts/textpaths on edges. * - * @param edges - list of nodes in a tree + * @param edges - list of edges in a tree */ function updateEdgeTexts(edges) { const textpath = self._textpaths @@ -614,17 +659,45 @@ export default class GroupTree { textpath.exit().remove(); } - const newTree = cloneExistingNodeStates( - growNewTree(this._renderTree(root.tree), this._width), - this._currentTree - ); + // Clear any existing error overlay + this._svg + .selectAll(".error-overlay-background, .error-overlay") + .remove(); + + if (hasInvalidDate) { + // // Add opacity to overlay background + this._svg + .append("rect") + .attr("class", "error-overlay-background") + .attr("width", this._rectWidth) + .attr("height", this._rectHeight) + .attr("x", this._rectLeftMargin) + .attr("y", this._rectTopMargin) + .attr("fill", "rgba(255, 255, 255, 0.8)"); + + // Show overlay text with error message + this._svg + .append("text") + .attr("class", "error-overlay") + .attr("x", this._rectWidth / 2 + 2 * this._rectLeftMargin) + .attr("y", this._rectHeight / 2 + 2 * this._rectTopMargin) + .style("fill", "red") + .style("font-size", "16px") + .text("Date not found in data"); + } else { + // Grow new tree + const newTree = cloneExistingNodeStates( + growNewTree(this._renderTree(root.tree), this._treeWidth), + this._currentTree + ); - // execute visualization operations on enter, update and exit selections - updateNodes(newTree.descendants(), this.nodeinfo); - updateEdges(newTree.descendants().slice(1), this.flowrate); - updateEdgeTexts(newTree.descendants().slice(1)); + // execute visualization operations on enter, update and exit selections + updateNodes(newTree.descendants(), this.nodeinfo); + updateEdges(newTree.descendants().slice(1), this.flowrate); + updateEdgeTexts(newTree.descendants().slice(1)); - // save the state of the now current tree, before next update - this._currentTree = doPostUpdateOperations(newTree); + // save the state of the now current tree, before next update + this._currentTree = doPostUpdateOperations(newTree); + } } } diff --git a/typescript/packages/group-tree-plot/src/GroupTreeAssembler/group_tree.css b/typescript/packages/group-tree-plot/src/GroupTreeAssembler/group_tree.css new file mode 100644 index 000000000..68b74425d --- /dev/null +++ b/typescript/packages/group-tree-plot/src/GroupTreeAssembler/group_tree.css @@ -0,0 +1,59 @@ +.link { + fill: none; + stroke: #5c5c5c; + opacity: 1; +} + +.grouptree_link { + opacity: 0.3; +} + +.grouptree_link__oilrate { + stroke: #60be6c; +} + +.grouptree_link__waterrate { + stroke: #0d1b9e; +} + +.grouptree_link__gasrate { + stroke: #c5221c; +} + +.grouptree_link__waterinjrate { + stroke: #00c3ff; +} + +.grouptree_link__gasinjrate { + stroke: #d6397a; +} + +.grouptree__node { + fill: #fff; + stroke: #60be6c; + stroke-width: 1px; + cursor: default; +} + +.grouptree__nodelabel { + font-size: 10px; + font-family: sans-serif; +} + +.grouptree__pressurelabel { + font-size: 10px; + font-family: "Statoil Sans Light", Lucida, Arial, Helvetica, sans-serif; +} + +.grouptree__pressureunit { + font-size: 9px; +} + +.grouptree__grupnet_text { + font-size: 12px; +} + +.grouptree__node--withchildren { + stroke-width: 2.5px; + cursor: pointer; +} diff --git a/typescript/packages/group-tree-plot/src/GroupTreePlot.tsx b/typescript/packages/group-tree-plot/src/GroupTreePlot.tsx new file mode 100644 index 000000000..d0eb6cf3d --- /dev/null +++ b/typescript/packages/group-tree-plot/src/GroupTreePlot.tsx @@ -0,0 +1,87 @@ +import React from "react"; + +import GroupTreeAssembler from "./GroupTreeAssembler/groupTreeAssembler"; +import type { DatedTree, EdgeMetadata, NodeMetadata } from "./types"; +import { isEqual } from "lodash"; + +export interface GroupTreePlotProps { + id: string; + edgeMetadataList: EdgeMetadata[]; + nodeMetadataList: NodeMetadata[]; + datedTrees: DatedTree[]; + selectedEdgeKey: string; + selectedNodeKey: string; + selectedDateTime: string; +} + +export const GroupTreePlot: React.FC = ( + props: GroupTreePlotProps +) => { + const divRef = React.useRef(null); + const groupTreeAssemblerRef = React.useRef(); + + // State to ensure divRef is defined before creating GroupTree + const [isMounted, setIsMounted] = React.useState(false); + + // Remove when typescript version is implemented using ref + const [prevId, setPrevId] = React.useState(null); + + const [prevDatedTrees, setPrevDatedTrees] = React.useState< + DatedTree[] | null + >(null); + + const [prevSelectedEdgeKey, setPrevSelectedEdgeKey] = + React.useState(props.selectedEdgeKey); + const [prevSelectedNodeKey, setPrevSelectedNodeKey] = + React.useState(props.selectedNodeKey); + const [prevSelectedDateTime, setPrevSelectedDateTime] = + React.useState(props.selectedDateTime); + + React.useEffect(function initialRender() { + setIsMounted(true); + }, []); + + if ( + isMounted && + divRef.current && + (!isEqual(prevDatedTrees, props.datedTrees) || + prevId !== divRef.current.id) + ) { + setPrevDatedTrees(props.datedTrees); + setPrevId(divRef.current.id); + groupTreeAssemblerRef.current = new GroupTreeAssembler( + divRef.current.id, + props.datedTrees, + props.selectedEdgeKey, + props.selectedNodeKey, + props.selectedDateTime, + props.edgeMetadataList, + props.nodeMetadataList + ); + } + + if (prevSelectedEdgeKey !== props.selectedEdgeKey) { + setPrevSelectedEdgeKey(props.selectedEdgeKey); + if (groupTreeAssemblerRef.current) { + groupTreeAssemblerRef.current.flowrate = props.selectedEdgeKey; + } + } + + if (prevSelectedNodeKey !== props.selectedNodeKey) { + setPrevSelectedNodeKey(props.selectedNodeKey); + if (groupTreeAssemblerRef.current) { + groupTreeAssemblerRef.current.nodeinfo = props.selectedNodeKey; + } + } + + if (prevSelectedDateTime !== props.selectedDateTime) { + setPrevSelectedDateTime(props.selectedDateTime); + if (groupTreeAssemblerRef.current) { + groupTreeAssemblerRef.current.update(props.selectedDateTime); + } + } + + return
; +}; + +GroupTreePlot.displayName = "GroupTreePlot"; diff --git a/typescript/packages/group-tree-plot/src/index.ts b/typescript/packages/group-tree-plot/src/index.ts new file mode 100644 index 000000000..bcfe45c34 --- /dev/null +++ b/typescript/packages/group-tree-plot/src/index.ts @@ -0,0 +1,18 @@ +export { GroupTreePlot } from "./GroupTreePlot"; + +// Export types +export type { GroupTreePlotProps } from "./GroupTreePlot"; +export type { + NodeData, + NodeDataPropTypes, + NodeMetadata, + NodeMetadataPropTypes, + EdgeData, + EdgeDataPropTypes, + EdgeMetadata, + EdgeMetadataPropTypes, + RecursiveTreeNode, + RecursiveTreeNodePropTypes, + DatedTree, + DatedTreePropTypes, +} from "./types"; diff --git a/typescript/packages/group-tree-plot/src/storybook/GroupTreePlot.stories.tsx b/typescript/packages/group-tree-plot/src/storybook/GroupTreePlot.stories.tsx new file mode 100644 index 000000000..82da99dc2 --- /dev/null +++ b/typescript/packages/group-tree-plot/src/storybook/GroupTreePlot.stories.tsx @@ -0,0 +1,69 @@ +import React from "react"; +import { GroupTreePlot } from "../GroupTreePlot"; + +import type { EdgeMetadata, NodeMetadata } from "../types"; + +import { + exampleDatedTrees, + exampleDates, +} from "../../example-data/dated-trees"; + +/** + * Storybook test for the group tree plot component + */ +const Template = (args) => { + return ( + + ); +}; + +const edgeMetadataList: EdgeMetadata[] = [ + { key: "waterrate", label: "Water Rate", unit: "m3/s" }, + { key: "oilrate", label: "Oil Rate", unit: "m3/s" }, + { key: "gasrate", label: "Gas Rate", unit: "m3/s" }, + { key: "waterinjrate", label: "Water Injection Rate", unit: "m3/s" }, + { key: "gasinjrate", label: "Gas Injection Rate", unit: "m3/s" }, +]; + +const nodeMetadataList: NodeMetadata[] = [ + { key: "pressure", label: "Pressure", unit: "Bar" }, + { key: "bhp", label: "Bottom Hole Pressure", unit: "N/m2" }, + { key: "wmctl", label: "Missing label", unit: "Unknown unit" }, +]; + +export const Default = Template.bind({}); +Default.args = { + id: "grouptreeplot", + datedTrees: exampleDatedTrees, + edgeMetadataList: edgeMetadataList, + nodeMetadataList: nodeMetadataList, + selectedDateTime: exampleDates[0], + selectedEdgeKey: edgeMetadataList[0].key, + selectedNodeKey: nodeMetadataList[0].key, +}; +export default { + component: GroupTreePlot, + title: "GroupTreePlot/Demo", + argTypes: { + selectedDateTime: { + description: + "The selected `string` must be a date time present in one of the `dates` arrays in an element of the`datedTrees`-prop.\n\n", + }, + selectedEdgeKey: { + description: + "The selection `string` must be an edge key present in one of the `edge_data` objects in the `tree`-prop of an element in `datedTrees`-prop.\n\n", + }, + selectedNodeKey: { + description: + "The selected `string` must be a node key present in one of the `node_data` objects in the `tree`-prop of an element in `datedTrees`-prop.\n\n", + }, + }, +}; diff --git a/typescript/packages/group-tree-plot/src/types.ts b/typescript/packages/group-tree-plot/src/types.ts new file mode 100644 index 000000000..6c603748a --- /dev/null +++ b/typescript/packages/group-tree-plot/src/types.ts @@ -0,0 +1,85 @@ +import PropTypes from "prop-types"; + +// Node key and values map - one value per date in DatedTree +export interface NodeData { + [key: string]: number[]; +} +// Node key and metadata +export interface NodeMetadata { + key: string; + label: string; + unit?: string; +} + +// Edge key and values map - value per date in DatedTree +export interface EdgeData { + [key: string]: number[]; +} +// Edge key and metadata +export interface EdgeMetadata { + key: string; + label: string; + unit?: string; +} + +// Recursively defined tree node +// The snake_case naming is to match the python naming +export interface RecursiveTreeNode { + node_type: "Group" | "Well"; + node_label: string; + edge_label: string; + node_data: NodeData; + edge_data: EdgeData; + children?: RecursiveTreeNode[]; +} + +// Collection of trees with a dates +export interface DatedTree { + dates: string[]; + tree: RecursiveTreeNode; +} + +// --------------------------- PropTypes --------------------------------------- + +export const NodeDataPropTypes = PropTypes.objectOf( + PropTypes.arrayOf(PropTypes.number.isRequired).isRequired +); +export const NodeMetadataPropTypes = PropTypes.shape({ + key: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + unit: PropTypes.string, +}); + +export const EdgeDataPropTypes = PropTypes.objectOf( + PropTypes.arrayOf(PropTypes.number.isRequired).isRequired +); +export const EdgeMetadataPropTypes = PropTypes.shape({ + key: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + unit: PropTypes.string, +}); + +// Note: This is a solution for recursive definition for RecursiveTreeNode, as children is an optional array of RecursiveTreeNode. +// - Object.assign() resolves the issue of children being optional. +// - PropTypes.arrayOf(PropTypes.shape(RecursiveTreeNode).isRequired) resolves the issue of children being recursive. +const RecursiveTreeNodeShape: React.WeakValidationMap = { + node_label: PropTypes.string.isRequired, + edge_label: PropTypes.string.isRequired, + node_data: NodeDataPropTypes.isRequired, + edge_data: EdgeDataPropTypes.isRequired, +}; +Object.assign(RecursiveTreeNodeShape, { + node_type: PropTypes.oneOf(["Group", "Well"]).isRequired, + children: PropTypes.arrayOf( + PropTypes.shape(RecursiveTreeNodeShape).isRequired + ), +}); +export const RecursiveTreeNodePropTypes = PropTypes.shape( + RecursiveTreeNodeShape +).isRequired; + +// Collection of trees with dates +export const DatedTreePropTypes = PropTypes.shape({ + dates: PropTypes.arrayOf(PropTypes.string).isRequired, + tree: RecursiveTreeNodePropTypes, +}); diff --git a/typescript/packages/group-tree/tsconfig.json b/typescript/packages/group-tree-plot/tsconfig.json similarity index 51% rename from typescript/packages/group-tree/tsconfig.json rename to typescript/packages/group-tree-plot/tsconfig.json index 2dba43075..0d954e179 100644 --- a/typescript/packages/group-tree/tsconfig.json +++ b/typescript/packages/group-tree-plot/tsconfig.json @@ -5,11 +5,5 @@ "rootDir": "./src" }, "include": ["src/"], - "exclude": [ - "src/storybook", - "src/test", - "./**/*.test.tsx", - "./**/*.stories.tsx", - "./storybook" - ] + "exclude": ["src/test", "./**/*.test.tsx", "./**/*.stories.tsx"] } diff --git a/typescript/packages/group-tree/CHANGELOG.md b/typescript/packages/group-tree/CHANGELOG.md deleted file mode 100644 index 09c4682e7..000000000 --- a/typescript/packages/group-tree/CHANGELOG.md +++ /dev/null @@ -1,55 +0,0 @@ -## [1.0.7](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.6...group-tree@1.0.7) (2023-12-04) - - -### Bug Fixes - -* bump @equinor/videx-wellog from 0.8.0 to 0.8.1 in /typescript ([#1811](https://github.com/equinor/webviz-subsurface-components/issues/1811)) ([0e6a423](https://github.com/equinor/webviz-subsurface-components/commit/0e6a423b32bdcb1ac78597932ec0821687851dde)) - -## [1.0.6](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.5...group-tree@1.0.6) (2023-11-30) - - -### Bug Fixes - -* bump deck.gl from 8.9.31 to 8.9.32 in /typescript ([#1800](https://github.com/equinor/webviz-subsurface-components/issues/1800)) ([393230c](https://github.com/equinor/webviz-subsurface-components/commit/393230c28e4946d9d210ed4a7e33c893fee87bf0)) - -## [1.0.5](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.4...group-tree@1.0.5) (2023-11-13) - - -### Bug Fixes - -* bump to latest @emerson-eps/color-tables ([#1770](https://github.com/equinor/webviz-subsurface-components/issues/1770)) ([e67a285](https://github.com/equinor/webviz-subsurface-components/commit/e67a2856eced8f987bc61fa4a0a924b5a4886992)) - -## [1.0.4](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.3...group-tree@1.0.4) (2023-11-09) - - -### Bug Fixes - -* bump [@deck](https://github.com/deck).gl/core from 8.9.31 to 8.9.32 in /typescript ([#1764](https://github.com/equinor/webviz-subsurface-components/issues/1764)) ([5ab32b0](https://github.com/equinor/webviz-subsurface-components/commit/5ab32b0db7cac16d027624643604df2ee7402918)) - -## [1.0.3](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.2...group-tree@1.0.3) (2023-10-17) - - -### Bug Fixes - -* bump @equinor/eds-core-react from 0.32.x to 0.33.0 ([#1704](https://github.com/equinor/webviz-subsurface-components/issues/1704)) ([75c5de8](https://github.com/equinor/webviz-subsurface-components/commit/75c5de8cd069a6c0d1d87b54307e23cf5be1b4b3)) - -## [1.0.2](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.1...group-tree@1.0.2) (2023-10-17) - - -### Bug Fixes - -* audit fix prod dependencies ([#1707](https://github.com/equinor/webviz-subsurface-components/issues/1707)) ([b5dbcf8](https://github.com/equinor/webviz-subsurface-components/commit/b5dbcf8677d0f0424cfdf4c2d237b378de867e12)) - -## [1.0.1](https://github.com/equinor/webviz-subsurface-components/compare/group-tree@1.0.0...group-tree@1.0.1) (2023-10-13) - - -### Bug Fixes - -* bump d3-format from 1.4.5 to 3.1.0 in /typescript ([#1680](https://github.com/equinor/webviz-subsurface-components/issues/1680)) ([91f42d1](https://github.com/equinor/webviz-subsurface-components/commit/91f42d1b47c8c423ae8e4d720daf44f2b24730e4)) - -# 1.0.0 (2023-09-22) - - -### Features - -* New wellsLayer property: "simplifiedRendering". Default false. ([#1653](https://github.com/equinor/webviz-subsurface-components/issues/1653)) ([baffae1](https://github.com/equinor/webviz-subsurface-components/commit/baffae183456c027c6312a44e56071baec7c0ca3)) diff --git a/typescript/packages/group-tree/jest.config.js b/typescript/packages/group-tree/jest.config.js deleted file mode 100644 index 52c5e0f33..000000000 --- a/typescript/packages/group-tree/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('jest').Config} */ - -const config = { - preset: "../../jest.config.js", -}; - -module.exports = config; diff --git a/typescript/packages/group-tree/src/GroupTree.test.tsx b/typescript/packages/group-tree/src/GroupTree.test.tsx deleted file mode 100644 index d24551ade..000000000 --- a/typescript/packages/group-tree/src/GroupTree.test.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render } from "@testing-library/react"; -import "jest-styled-components"; -import React from "react"; -import { Wrapper } from "./test/TestWrapper"; -import GroupTree from "./GroupTree"; - -import exampleData from "../../../../example-data/group-tree.json"; - -describe.skip("Test GroupTree Default Component", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: ( - - ), - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); -}); diff --git a/typescript/packages/group-tree/src/GroupTree.tsx b/typescript/packages/group-tree/src/GroupTree.tsx deleted file mode 100644 index 1dee28276..000000000 --- a/typescript/packages/group-tree/src/GroupTree.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/** - * This file is created in order to let dash-generate-components extract metadata. - * At the moment, the library does not support generating components from typescript directly - * https://github.com/plotly/dash/issues/719 - */ - -import PropTypes from "prop-types"; -import React from "react"; -import type { GroupTreeProps } from "./components/GroupTreeComponent"; -import GroupTreeComponent from "./components/GroupTreeComponent"; - -const GroupTree = (props: GroupTreeProps) => { - return ( - - ); -}; - -GroupTree.propTypes = { - /** - * 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: PropTypes.string.isRequired, - /** - * Array of JSON objects describing group tree data. - */ - data: PropTypes.arrayOf(PropTypes.object), - - edgeOptions: PropTypes.arrayOf(PropTypes.object), - nodeOptions: PropTypes.arrayOf(PropTypes.object), -}; - -export type { GroupTreeProps }; -export default GroupTree; diff --git a/typescript/packages/group-tree/src/GroupTree_performance.test.tsx b/typescript/packages/group-tree/src/GroupTree_performance.test.tsx deleted file mode 100644 index 70385f09a..000000000 --- a/typescript/packages/group-tree/src/GroupTree_performance.test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render } from "@testing-library/react"; -import "jest-styled-components"; -import React, { Profiler } from "react"; -import * as core from "@actions/core"; -import GroupTree from "./GroupTree"; -import { Wrapper } from "./test/TestWrapper"; -import logTimes, { obj } from "./test/performanceMetrics"; - -import exampleData from "../../../../example-data/group-tree.json"; - -describe("Test GroupTree perfomance", () => { - it("initial performance test", () => { - render( - Wrapper({ - children: ( - - - - ), - }) - ); - }); - - const no_of_renders = obj.perf_metrics.length; - if (no_of_renders > 2) { - core.setFailed( - "GroupTree Component seems to have performance issues. Actual number of renders = " + - no_of_renders + - " .Expected number of renders <= 2 " - ); - } - for (let i = 0; i < no_of_renders; i++) { - core.info( - "Render number: " + (i + 1) + " | Metrics: " + obj.perf_metrics[i] - ); - if (obj.perf_metrics[i][2] > 100) { - core.setFailed( - "GroupTree Component seems to have performance issues. Actual render time:" + - obj.perf_metrics[i][2] + - " Expected render time - less than 100ms" - ); - } - } -}); diff --git a/typescript/packages/group-tree/src/__snapshots__/GroupTree.test.tsx.snap b/typescript/packages/group-tree/src/__snapshots__/GroupTree.test.tsx.snap deleted file mode 100644 index 337a07529..000000000 --- a/typescript/packages/group-tree/src/__snapshots__/GroupTree.test.tsx.snap +++ /dev/null @@ -1,492 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test GroupTree Default Component snapshot test 1`] = ` -.c3 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c4 { - margin: 0; -} - -.c0 { - height: 64px; - top: 0; - position: -webkit-sticky; - position: sticky; - background: var(--eds_ui_background__default,rgba(255,255,255,1)); - box-sizing: border-box; - z-index: 250; - display: grid; - grid-column-gap: 40px; - grid-template-columns: auto 1fr auto; - grid-template-areas: 'left center right'; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom: 2px var(--eds_ui_background__light,rgba(247,247,247,1)); - padding-left: 40px; - padding-top: 8px; - padding-right: 40px; - padding-bottom: 8px; - margin: 0; - color: rgba(61,61,61,1); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.000em; - -webkit-letter-spacing: 0.013em; - -moz-letter-spacing: 0.013em; - -ms-letter-spacing: 0.013em; - letter-spacing: 0.013em; - text-align: left; -} - -.c6 { - grid-area: right; - text-align: right; -} - -.c1 { - grid-area: left; - display: grid; - grid-template-columns: auto auto; - grid-gap: 24px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c5 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c5:active, -.c5:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c5:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c5:disabled .arrow-icon { - fill: red; -} - -.c5:disabled:focus, -.c5:disabled:active { - outline: none; -} - -.c2 { - min-width: 100px; - width: 100%; -} - -
-
-
-
- - -
-
- - -
-
-
-
- - Time Steps - - - - - - - - - - - - - -
-
-
-
- - - - - Water Rate 20 -Oil Rate 30 -Gas Rate 40 -Water Injection Rate 50 -Gas Injection Rate 60 - - - - - - Water Rate 25 -Oil Rate 35 -Gas Rate 45 -Water Injection Rate 55 -Gas Injection Rate 65 - - - - - - - - - - - - - - - TRE_1 - - - 5 - - - - Pressure 5 - - - - - - - TRE_1_1 - - - 20 - - - - Pressure 20 -Bottom Hole Pressure 11 -wmctl 12 - - - - - - - TRE_1_2 - - - 22 - - - - Pressure 22 -wmctl 10 - - - - - -
-
-`; diff --git a/typescript/packages/group-tree/src/components/DataLoader.tsx b/typescript/packages/group-tree/src/components/DataLoader.tsx deleted file mode 100644 index 537473fe5..000000000 --- a/typescript/packages/group-tree/src/components/DataLoader.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* 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 { Data, DataInfos, UISettings } from "../redux/types"; - -interface Props { - id: string; - data: Data; - edge_options: DataInfos; - node_options: DataInfos; - initial_index: [number, number]; - children: ReactNode; -} - -export const DataContext = React.createContext([]); - -const DataProvider: React.FC = ({ - children, - id, - data, - edge_options, - node_options, - initial_index, -}: PropsWithChildren) => { - const preloadedState = useMemo(() => { - // Use "initial_index" from previous data if it refers to a valid date otherwise use first date. - const idx1 = initial_index?.[0]; - const idx2 = initial_index?.[1]; - const initialDateTime = - data.length > idx1 && data[idx1].dates.length > idx2 - ? data[idx1].dates[idx2] - : data[0].dates[0]; - - const initialFlowRate = - edge_options?.length > 0 ? edge_options[0].name : ""; - - const intialNodeInfo = - node_options?.length > 0 ? node_options[0].name : ""; - - return { - id: id, - ui: { - currentDateTime: initialDateTime, - currentFlowRate: initialFlowRate, - currentNodeInfo: intialNodeInfo, - } as UISettings, - }; - }, [id, data]); - - const store = useMemo( - () => createReduxStore(preloadedState), - [preloadedState] - ); - - return ( - - {children} - - ); -}; - -export default DataProvider; diff --git a/typescript/packages/group-tree/src/components/GroupTreeComponent.test.tsx b/typescript/packages/group-tree/src/components/GroupTreeComponent.test.tsx deleted file mode 100644 index 17cfe2dbc..000000000 --- a/typescript/packages/group-tree/src/components/GroupTreeComponent.test.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render } from "@testing-library/react"; -import "jest-styled-components"; -import React from "react"; -import { Wrapper } from "./../test/TestWrapper"; -import GroupTreeComponent from "./GroupTreeComponent"; -import type { Data } from "../redux/types"; - -import exampleData from "../../../../../example-data/group-tree.json"; - -describe.skip("Test GroupTree Component", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: ( - - ), - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); -}); diff --git a/typescript/packages/group-tree/src/components/GroupTreeComponent.tsx b/typescript/packages/group-tree/src/components/GroupTreeComponent.tsx deleted file mode 100644 index cbe6b6d3b..000000000 --- a/typescript/packages/group-tree/src/components/GroupTreeComponent.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React, { useCallback, useState } from "react"; -import type { Data, DataInfos } from "../redux/types"; -import DataProvider from "./DataLoader"; -import GroupTreeViewer from "./GroupTreeViewer"; - -//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: Data; - - /** - * Arrays of options. Used in drop down selectors. - */ - edgeOptions: DataInfos; - nodeOptions: DataInfos; -} - -const GroupTreeComponent: React.FC = React.memo( - ({ id, data, edgeOptions, nodeOptions }: GroupTreeProps) => { - const [index, setIndex] = useState([0, 0] as [number, number]); - - const currentDateTimeChangedCallBack = useCallback( - (currentDateTime: string) => { - const current_tree_index = data.findIndex((e) => { - return e.dates.includes(currentDateTime); - }); - const date_index = - data[current_tree_index].dates.indexOf(currentDateTime); - - setIndex([current_tree_index, date_index]); - }, - [data] - ); - - return ( - - - - ); - } -); - -GroupTreeComponent.displayName = "GroupTreeComponent"; -export default GroupTreeComponent; diff --git a/typescript/packages/group-tree/src/components/GroupTreeViewer.test.tsx b/typescript/packages/group-tree/src/components/GroupTreeViewer.test.tsx deleted file mode 100644 index f6b75df79..000000000 --- a/typescript/packages/group-tree/src/components/GroupTreeViewer.test.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render } from "@testing-library/react"; -import "jest-styled-components"; -import React from "react"; -import { Wrapper } from "../test/TestWrapper"; -import GroupTreeViewer from "./GroupTreeViewer"; - -describe.skip("Test GroupTreeViewer", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: ( - currentDateTime} - /> - ), - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); -}); diff --git a/typescript/packages/group-tree/src/components/GroupTreeViewer.tsx b/typescript/packages/group-tree/src/components/GroupTreeViewer.tsx deleted file mode 100644 index f7442330b..000000000 --- a/typescript/packages/group-tree/src/components/GroupTreeViewer.tsx +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ // remove when ready to fix these. - -import { styled } from "@mui/material/styles"; -import { cloneDeep } from "lodash"; -import React, { useContext, useEffect, useRef } from "react"; -import { useSelector } from "react-redux"; -import type { GroupTreeState } from "../redux/store"; -import { DataContext } from "./DataLoader"; -import "./Plot/dynamic_tree.css"; -import GroupTree from "./Plot/group_tree"; -import SettingsBar from "./Settings/SettingsBar"; -import type { DataInfos } from "../redux/types"; - -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 Props { - id: string; - edge_options: DataInfos; - node_options: DataInfos; - currentDateTimeChangedCallBack: (currentDateTime: string) => void; -} - -const GroupTreeViewer: React.FC = ({ - id, - edge_options, - node_options, - currentDateTimeChangedCallBack, -}: Props) => { - const divRef = useRef(null); - const data = useContext(DataContext); - - const renderer = useRef(); - - const currentDateTime = useSelector( - (state: GroupTreeState) => state.ui.currentDateTime - ); - const currentFlowRate = useSelector( - (state: GroupTreeState) => state.ui.currentFlowRate - ); - const currentNodeInfo = useSelector( - (state: GroupTreeState) => state.ui.currentNodeInfo - ); - - useEffect(() => { - renderer.current = new GroupTree( - id, - cloneDeep(data), - currentFlowRate, - currentNodeInfo, - currentDateTime, - edge_options, - node_options - ); - }, [data]); - - useEffect(() => { - if (!renderer.current) return; - - renderer.current.update(currentDateTime); - - if (typeof currentDateTimeChangedCallBack !== "undefined") { - currentDateTimeChangedCallBack(currentDateTime); - } - }, [currentDateTime]); - - useEffect(() => { - if (!renderer.current) return; - renderer.current.flowrate = currentFlowRate; - }, [currentFlowRate]); - - useEffect(() => { - if (!renderer.current) return; - renderer.current.nodeinfo = currentNodeInfo; - }, [currentNodeInfo]); - - return ( - - -
- {/* */} - - ); -}; - -GroupTreeViewer.displayName = "GroupTreeViewer"; -export default GroupTreeViewer; diff --git a/typescript/packages/group-tree/src/components/Plot/dynamic_tree.css b/typescript/packages/group-tree/src/components/Plot/dynamic_tree.css deleted file mode 100644 index eb7274026..000000000 --- a/typescript/packages/group-tree/src/components/Plot/dynamic_tree.css +++ /dev/null @@ -1,201 +0,0 @@ -.slider, -.slider-inset, -.slider-overlay { - stroke-linecap: round; -} - -.slider { - stroke-width: 8px; -} - -.slider-inset { - stroke: #b20276; - stroke-width: 8px; -} - -.slider-overlay { - pointer-events: stroke; - cursor: pointer; -} - -.handle { - fill: #fff; - stroke: #b20276; - stroke-opacity: 0.5; - stroke-width: 1.25px; -} - -#sensitivity-slider-plot { - position: relative; -} - -.sensitivity-slider-plot__graph-area { - fill: steelblue; - fill-opacity: 0.4 -} - -.sensitivity-slider-plot__graph-line { - stroke: steelblue; - stroke-width: 1; - fill: none -} - -.sensitivity-slider-plot__graph-overlay { - fill: none; - pointer-events: all; -} - -.sensitivity-slider-plot__graph-container { - background-color: white; - z-index: 1; -} - -.sensitivity-slider-plot__slider-container { - background-color: white; - padding: 0; -} - -.sensitivity-slider-plot__graph-focus-circle { - fill: none; - stroke: black; - r: 4.5 -} - -.sensitivity-slider-plot__graph-focus-line { - fill: none; - stroke: black; - stroke-width: 1.5px; - stroke-dasharray: 3 3; -} - -.sensitivity-slider-plot__graph-focus-text { - /*x: 9px;*/ - /*dy: -0.35em;*/ - font-size: 12px; -} - -.sensitivity-slider-plot__slider-cell { - fill: none; -} - -.sensitivity-slider-plot__slider-col-header { - /*fill: none;*/ -} - -.sensitivity-slider-plot__slider-row-header { - /*fill: none;*/ -} - -.sensitivity-slider-plot__slider-col-header-label { - text-anchor: middle; - alignment-baseline: hanging; - font-size: 30px; - fill: black; -} - -.sensitivity-slider-plot__slider-row-header-label { - text-anchor: end; - alignment-baseline: central; - font-size: 10px; - fill: black; -} - -.sensitivity-slider-plot__slide-bar-label { - text-anchor: end; - alignment-baseline: central; - font-size: 12px; - fill: black; -} - -.sensitivity-slider-plot__slider-bar-background { - fill: grey; - stroke: black; - stroke-width: 0.5px; - rx: 4; - ry: 4; -} - -.sensitivity-slider-plot__slider-bar-main { - fill: rgb(210, 15, 140); - stroke: black; - stroke-width: 0.5px; - rx: 4; - ry: 4; -} - -.sensitivity-slider-plot__slider-bar-interaction { - fill: rgb(250, 150, 0); - stroke: black; - stroke-width: 0.5px; - rx: 4; - ry: 4; -} - -.affix { - top: 0; -} - -.sensitivity-slider-plot__description.mfp-wrap { - z-index: initial; -} - -.link { - fill: none; - stroke: #5c5c5c; - opacity: 1; -} - -.grouptree_link { - opacity: 0.3; -} - -.grouptree_link__oilrate { - stroke: #60be6c; -} - -.grouptree_link__waterrate { - stroke: #0d1b9e; -} - -.grouptree_link__gasrate { - stroke: #c5221c; -} - -.grouptree_link__waterinjrate { - stroke: #00c3ff; -} - -.grouptree_link__gasinjrate { - stroke: #d6397a; -} - -.grouptree__node { - fill: #fff; - stroke: #60be6c; - stroke-width: 1px; - cursor: default; -} - -.grouptree__nodelabel { - font-size: 10px; - font-family: sans-serif; -} - -.grouptree__pressurelabel { - font-size: 10px; - font-family: "Statoil Sans Light", Lucida, Arial, Helvetica, sans-serif; -} - -.grouptree__pressureunit{ - font-size: 9px; -} - -.grouptree__grupnet_text{ - font-size: 12px; -} - -.grouptree__node--withchildren { - stroke-width: 2.5px; - cursor: pointer; - -} diff --git a/typescript/packages/group-tree/src/components/Settings/DateTimeSlider.test.tsx b/typescript/packages/group-tree/src/components/Settings/DateTimeSlider.test.tsx deleted file mode 100644 index ce9da3d53..000000000 --- a/typescript/packages/group-tree/src/components/Settings/DateTimeSlider.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render, screen } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import "jest-styled-components"; -import React from "react"; -import { testStore, Wrapper } from "../../test/TestWrapper"; -import DateTimeSlider from "./DateTimeSlider"; - -describe("Test Date-Time Slider", () => { - it("snapshot test", () => { - const { container } = render(Wrapper({ children: })); - render(Wrapper({ children: })); - expect(container.firstChild).toMatchSnapshot(); - }); - it("test slider", async () => { - render(Wrapper({ children: })); - userEvent.type(screen.getByRole("slider"), "{arrowright}"); - expect(testStore.dispatch).toHaveBeenCalledTimes(1); - expect(testStore.dispatch).toHaveBeenNthCalledWith(1, { - payload: undefined, - type: "ui/updateCurrentDateTime", - }); - }); -}); diff --git a/typescript/packages/group-tree/src/components/Settings/FlowRateSelector.test.tsx b/typescript/packages/group-tree/src/components/Settings/FlowRateSelector.test.tsx deleted file mode 100644 index 5ca7ffb97..000000000 --- a/typescript/packages/group-tree/src/components/Settings/FlowRateSelector.test.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render, screen } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import "jest-styled-components"; -import React from "react"; -import { testStore, Wrapper } from "../../test/TestWrapper"; -import FlowRateSelector from "./FlowRateSelector"; - -const edge_options = [ - { name: "waterrate", label: "Water Rate" }, - { name: "oilrate", label: "Oil Rate" }, - { name: "gasrate", label: "Gas Rate" }, - { name: "waterinjrate", label: "Water Injection Rate" }, - { name: "gasinjrate", label: "Gas Injection Rate" }, -]; - -describe("Test flow rate selector component", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: , - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); - it("select 'water rate' option to dispatch redux action", async () => { - render( - Wrapper({ - children: , - }) - ); - userEvent.selectOptions( - screen.getByRole("combobox", { name: "Flow Rate" }), - "waterrate" - ); - expect(testStore.dispatch).toHaveBeenCalledTimes(1); - expect(testStore.dispatch).toHaveBeenCalledWith({ - payload: "waterrate", - type: "ui/updateCurrentFlowRate", - }); - }); -}); diff --git a/typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.test.tsx b/typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.test.tsx deleted file mode 100644 index 76524f860..000000000 --- a/typescript/packages/group-tree/src/components/Settings/NodeInfoSelector.test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render, screen } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import "jest-styled-components"; -import React from "react"; -import { testStore, Wrapper } from "../../test/TestWrapper"; -import NodeInfoSelector from "./NodeInfoSelector"; - -const node_options = [ - { name: "pressure", label: "Pressure" }, - { name: "bhp", label: "Bottom Hole Pressure" }, -]; - -describe("Test flow rate selector component", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: , - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); - it("select 'Pressure' option to dispatch redux action", async () => { - render( - Wrapper({ - children: , - }) - ); - userEvent.selectOptions( - screen.getByRole("combobox", { name: "Node Data" }), - "pressure" - ); - expect(testStore.dispatch).toHaveBeenCalledTimes(1); - expect(testStore.dispatch).toHaveBeenCalledWith({ - payload: "pressure", - type: "ui/updateCurrentNodeInfo", - }); - }); -}); diff --git a/typescript/packages/group-tree/src/components/Settings/SettingsBar.test.tsx b/typescript/packages/group-tree/src/components/Settings/SettingsBar.test.tsx deleted file mode 100644 index 5ee98e223..000000000 --- a/typescript/packages/group-tree/src/components/Settings/SettingsBar.test.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import "@testing-library/jest-dom/extend-expect"; -import { render } from "@testing-library/react"; -import "jest-styled-components"; -import React from "react"; -import { Wrapper } from "../../test/TestWrapper"; -import SettingsBar from "./SettingsBar"; - -const edge_options = [ - { name: "waterrate", label: "Water Rate" }, - { name: "oilrate", label: "Oil Rate" }, - { name: "gasrate", label: "Gas Rate" }, - { name: "waterinjrate", label: "Water Injection Rate" }, - { name: "gasinjrate", label: "Gas Injection Rate" }, -]; - -const node_options = [ - { name: "pressure", label: "Pressure" }, - { name: "bhp", label: "Bottom Hole Pressure" }, -]; - -describe("Test Settins Bar component", () => { - it("snapshot test", () => { - const { container } = render( - Wrapper({ - children: ( - - ), - }) - ); - expect(container.firstChild).toMatchSnapshot(); - }); -}); diff --git a/typescript/packages/group-tree/src/components/Settings/__snapshots__/DateTimeSlider.test.tsx.snap b/typescript/packages/group-tree/src/components/Settings/__snapshots__/DateTimeSlider.test.tsx.snap deleted file mode 100644 index 1cebc98cd..000000000 --- a/typescript/packages/group-tree/src/components/Settings/__snapshots__/DateTimeSlider.test.tsx.snap +++ /dev/null @@ -1,76 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test Date-Time Slider snapshot test 1`] = ` -
- - Time Steps - - - - - - - - - - - - - -
-`; diff --git a/typescript/packages/group-tree/src/components/Settings/__snapshots__/FlowRateSelector.test.tsx.snap b/typescript/packages/group-tree/src/components/Settings/__snapshots__/FlowRateSelector.test.tsx.snap deleted file mode 100644 index e9f903aa1..000000000 --- a/typescript/packages/group-tree/src/components/Settings/__snapshots__/FlowRateSelector.test.tsx.snap +++ /dev/null @@ -1,134 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test flow rate selector component snapshot test 1`] = ` -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c2 { - margin: 0; -} - -.c0 { - min-width: 100px; - width: 100%; -} - -.c3 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - margin: 0; - color: var(--eds_text__static_icons__default,rgba(61,61,61,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c3:active, -.c3:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c3:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c3:disabled .arrow-icon { - fill: red; -} - -.c3:disabled:focus, -.c3:disabled:active { - outline: none; -} - -
- - -
-`; diff --git a/typescript/packages/group-tree/src/components/Settings/__snapshots__/NodeInfoSelector.test.tsx.snap b/typescript/packages/group-tree/src/components/Settings/__snapshots__/NodeInfoSelector.test.tsx.snap deleted file mode 100644 index 3925b007b..000000000 --- a/typescript/packages/group-tree/src/components/Settings/__snapshots__/NodeInfoSelector.test.tsx.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test flow rate selector component snapshot test 1`] = ` -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c2 { - margin: 0; -} - -.c0 { - min-width: 100px; - width: 100%; -} - -.c3 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - margin: 0; - color: var(--eds_text__static_icons__default,rgba(61,61,61,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c3:active, -.c3:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c3:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c3:disabled .arrow-icon { - fill: red; -} - -.c3:disabled:focus, -.c3:disabled:active { - outline: none; -} - -
- - -
-`; diff --git a/typescript/packages/group-tree/src/components/Settings/__snapshots__/SettingsBar.test.tsx.snap b/typescript/packages/group-tree/src/components/Settings/__snapshots__/SettingsBar.test.tsx.snap deleted file mode 100644 index 313ae5727..000000000 --- a/typescript/packages/group-tree/src/components/Settings/__snapshots__/SettingsBar.test.tsx.snap +++ /dev/null @@ -1,310 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test Settins Bar component snapshot test 1`] = ` -.c4 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c5 { - margin: 0; -} - -.c0 { - background: var(--eds_ui_background__default,rgba(255,255,255,1)); - box-shadow: 0 0 1px rgba(0,0,0,0.14); -} - -.c1 { - height: 64px; - background: var(--eds_ui_background__default,rgba(255,255,255,1)); - box-sizing: border-box; - display: grid; - grid-column-gap: 24px; - grid-template-columns: auto 1fr auto; - grid-template-areas: 'left center right'; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom: 2px solid var(--eds_ui_background__light,rgba(247,247,247,1)); - padding-left: 24px; - padding-top: 8px; - padding-right: 24px; - padding-bottom: 8px; - margin: 0; - color: var(--eds_navigation__menu_title_color,rgba(61,61,61,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.000em; - -webkit-letter-spacing: 0.013em; - -moz-letter-spacing: 0.013em; - -ms-letter-spacing: 0.013em; - letter-spacing: 0.013em; - text-align: left; - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1100; -} - -.c7 { - grid-area: right; - text-align: right; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -} - -.c2 { - grid-area: left; - display: grid; - grid-template-columns: auto auto; - grid-gap: 12px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c3 { - min-width: 100px; - width: 100%; -} - -.c6 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - margin: 0; - color: var(--eds_text__static_icons__default,rgba(61,61,61,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c6:active, -.c6:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c6:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"),linear-gradient( to bottom,var(--eds_ui_background__light,rgba(247,247,247,1)) 0%,var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c6:disabled .arrow-icon { - fill: red; -} - -.c6:disabled:focus, -.c6:disabled:active { - outline: none; -} - -
-
-
- - -
-
- - -
-
-
-
- - Time Steps - - - - - - - - - - - - - -
-
-
-`; diff --git a/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeComponent.test.tsx.snap b/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeComponent.test.tsx.snap deleted file mode 100644 index dc10f888e..000000000 --- a/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeComponent.test.tsx.snap +++ /dev/null @@ -1,492 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test GroupTree Component snapshot test 1`] = ` -.c3 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c4 { - margin: 0; -} - -.c0 { - height: 64px; - top: 0; - position: -webkit-sticky; - position: sticky; - background: var(--eds_ui_background__default,rgba(255,255,255,1)); - box-sizing: border-box; - z-index: 250; - display: grid; - grid-column-gap: 40px; - grid-template-columns: auto 1fr auto; - grid-template-areas: 'left center right'; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom: 2px var(--eds_ui_background__light,rgba(247,247,247,1)); - padding-left: 40px; - padding-top: 8px; - padding-right: 40px; - padding-bottom: 8px; - margin: 0; - color: rgba(61,61,61,1); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.000em; - -webkit-letter-spacing: 0.013em; - -moz-letter-spacing: 0.013em; - -ms-letter-spacing: 0.013em; - letter-spacing: 0.013em; - text-align: left; -} - -.c6 { - grid-area: right; - text-align: right; -} - -.c1 { - grid-area: left; - display: grid; - grid-template-columns: auto auto; - grid-gap: 24px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c5 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c5:active, -.c5:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c5:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c5:disabled .arrow-icon { - fill: red; -} - -.c5:disabled:focus, -.c5:disabled:active { - outline: none; -} - -.c2 { - min-width: 100px; - width: 100%; -} - -
-
-
-
- - -
-
- - -
-
-
-
- - Time Steps - - - - - - - - - - - - - -
-
-
-
- - - - - Water Rate 20 -Oil Rate 30 -Gas Rate 40 -Water Injection Rate 50 -Gas Injection Rate 60 - - - - - - Water Rate 25 -Oil Rate 35 -Gas Rate 45 -Water Injection Rate 55 -Gas Injection Rate 65 - - - - - - - - - - - - - - - TRE_1 - - - 5 - - - - Pressure 5 - - - - - - - TRE_1_1 - - - 20 - - - - Pressure 20 -Bottom Hole Pressure 11 -wmctl 12 - - - - - - - TRE_1_2 - - - 22 - - - - Pressure 22 -wmctl 10 - - - - - -
-
-`; diff --git a/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeViewer.test.tsx.snap b/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeViewer.test.tsx.snap deleted file mode 100644 index d0082affa..000000000 --- a/typescript/packages/group-tree/src/components/__snapshots__/GroupTreeViewer.test.tsx.snap +++ /dev/null @@ -1,492 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test GroupTreeViewer snapshot test 1`] = ` -.c3 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - position: relative; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 0.750rem; - font-weight: 500; - line-height: 1.333em; - text-align: left; - margin-left: 8px; - margin-right: 8px; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); -} - -.c4 { - margin: 0; -} - -.c0 { - height: 64px; - top: 0; - position: -webkit-sticky; - position: sticky; - background: var(--eds_ui_background__default,rgba(255,255,255,1)); - box-sizing: border-box; - z-index: 250; - display: grid; - grid-column-gap: 40px; - grid-template-columns: auto 1fr auto; - grid-template-areas: 'left center right'; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom: 2px var(--eds_ui_background__light,rgba(247,247,247,1)); - padding-left: 40px; - padding-top: 8px; - padding-right: 40px; - padding-bottom: 8px; - margin: 0; - color: rgba(61,61,61,1); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.000em; - -webkit-letter-spacing: 0.013em; - -moz-letter-spacing: 0.013em; - -ms-letter-spacing: 0.013em; - letter-spacing: 0.013em; - text-align: left; -} - -.c6 { - grid-area: right; - text-align: right; -} - -.c1 { - grid-area: left; - display: grid; - grid-template-columns: auto auto; - grid-gap: 24px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c5 { - border: none; - border-radius: 0; - box-shadow: inset 0 -1px 0 0 var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - padding-left: 8px; - padding-top: 6px; - padding-right: 8px; - padding-bottom: 6px; - margin: 0; - color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1)); - font-family: Equinor; - font-size: 1.000rem; - font-weight: 400; - line-height: 1.500em; - -webkit-letter-spacing: 0.025em; - -moz-letter-spacing: 0.025em; - -ms-letter-spacing: 0.025em; - letter-spacing: 0.025em; - text-align: left; - padding-right: calc(8px *2 + 24px); - display: block; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%236f6f6f' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - background-repeat: no-repeat,repeat; - background-position: right 8px top 50%; - width: 100%; -} - -.c5:active, -.c5:focus { - box-shadow: none; - outline: 2px solid var(--eds_interactive_primary__resting,rgba(0,112,121,1)); - outline-offset: 0px; -} - -.c5:disabled { - color: var(--eds_interactive__disabled__text,rgba(190,190,190,1)); - background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23bebebe' d='M7 9.5l5 5 5-5H7z'/%3E%3C/svg%3E"), linear-gradient( to bottom, var(--eds_ui_background__light,rgba(247,247,247,1)) 0%, var(--eds_ui_background__light,rgba(247,247,247,1)) 100% ); - cursor: not-allowed; - box-shadow: none; - outline: none; -} - -.c5:disabled .arrow-icon { - fill: red; -} - -.c5:disabled:focus, -.c5:disabled:active { - outline: none; -} - -.c2 { - min-width: 100px; - width: 100%; -} - -
-
-
-
- - -
-
- - -
-
-
-
- - Time Steps - - - - - - - - - - - - - -
-
-
-
- - - - - Water Rate 20 -Oil Rate 30 -Gas Rate 40 -Water Injection Rate 50 -Gas Injection Rate 60 - - - - - - Water Rate 25 -Oil Rate 35 -Gas Rate 45 -Water Injection Rate 55 -Gas Injection Rate 65 - - - - - - - - - - - - - - - TRE_1 - - - 5 - - - - Pressure 5 - - - - - - - TRE_1_1 - - - 20 - - - - Pressure 20 -Bottom Hole Pressure 11 -wmctl 12 - - - - - - - TRE_1_2 - - - 22 - - - - Pressure 22 -wmctl 10 - - - - - -
-
-`; diff --git a/typescript/packages/group-tree/src/index.ts b/typescript/packages/group-tree/src/index.ts deleted file mode 100644 index a1e057646..000000000 --- a/typescript/packages/group-tree/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./GroupTree"; -export type { GroupTreeProps } from "./GroupTree"; diff --git a/typescript/packages/group-tree/src/redux/types.ts b/typescript/packages/group-tree/src/redux/types.ts deleted file mode 100644 index 48c2f2bd7..000000000 --- a/typescript/packages/group-tree/src/redux/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type DatedTree = { - dates: [string]; - tree: Node; -}; -export type Data = DatedTree[]; - -export interface Node { - node_label: string; - node_type: "Group" | "Well"; - //node_data - edge_label: string; - //edge_data - children: Node[]; -} - -export interface DataInfo { - name: string; - label: string; -} -export type DataInfos = DataInfo[]; - -export interface UISettings { - currentDateTime: string; - currentFlowRate: string; - currentNodeInfo: string; -} diff --git a/typescript/packages/group-tree/src/storybook/GroupTreeComponent.stories.tsx b/typescript/packages/group-tree/src/storybook/GroupTreeComponent.stories.tsx deleted file mode 100644 index d9934931e..000000000 --- a/typescript/packages/group-tree/src/storybook/GroupTreeComponent.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from "react"; -import GroupTreeComponent from "../components/GroupTreeComponent"; - -export default { - component: GroupTreeComponent, - title: "GroupTree", -}; - -const edge_options = [ - { name: "waterrate", label: "Water Rate", unit: "m3/s" }, - { name: "oilrate", label: "Oil Rate", unit: "m3/s" }, - { name: "gasrate", label: "Gas Rate", unit: "m3/s" }, - { name: "waterinjrate", label: "Water Injection Rate", unit: "m3/s" }, - { name: "gasinjrate", label: "Gas Injection Rate", unit: "m3/s" }, -]; - -const node_options = [ - { name: "pressure", label: "Pressure", unit: "Bar" }, - { name: "bhp", label: "Bottom Hole Pressure", unit: "N/m2" }, -]; - -const Template = (args) => { - return ; -}; - -export const Default = Template.bind({}); -Default.args = { - id: "grouptree", - data: require("../../../../../example-data/group-tree.json"), - edgeOptions: edge_options, - nodeOptions: node_options, -}; diff --git a/typescript/packages/group-tree/src/storybook/components/DateTimeSlider.stories.tsx b/typescript/packages/group-tree/src/storybook/components/DateTimeSlider.stories.tsx deleted file mode 100644 index 219ae5391..000000000 --- a/typescript/packages/group-tree/src/storybook/components/DateTimeSlider.stories.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from "react"; -import DataProvider from "../../components/DataLoader"; -import DateTimeSlider from "../../components/Settings/DateTimeSlider"; - -export default { - component: DateTimeSlider, - title: "GroupTree/Components/Settings/DateTimeSlider", - argTypes: { - id: { - description: - "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.", - }, - data: { - description: "Array of JSON objects describing group tree data.", - }, - }, -}; - -const Template = (args) => { - return ( - - - - ); -}; - -export const Default = Template.bind({}); -Default.args = { - id: "grouptree", - data: require("../../../../../../example-data/group-tree.json"), -}; diff --git a/typescript/packages/group-tree/src/storybook/components/FlowRateSelector.stories.tsx b/typescript/packages/group-tree/src/storybook/components/FlowRateSelector.stories.tsx deleted file mode 100644 index 74e7fe0b6..000000000 --- a/typescript/packages/group-tree/src/storybook/components/FlowRateSelector.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import DataProvider from "../../components/DataLoader"; -import FlowRateSelector from "../../components/Settings/FlowRateSelector"; - -const edge_options = [ - { name: "waterrate", label: "Water Rate" }, - { name: "oilrate", label: "Oil Rate" }, - { name: "gasrate", label: "Gas Rate" }, - { name: "waterinjrate", label: "Water Injection Rate" }, - { name: "gasinjrate", label: "Gas Injection Rate" }, -]; - -export default { - component: FlowRateSelector, - title: "GroupTree/Components/Settings/FLowRateSelector", - argTypes: { - id: { - description: - "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.", - }, - data: { - description: "Array of JSON objects describing group tree data.", - }, - }, -}; - -const Template = (args) => { - return ( - - - - ); -}; - -export const Default = Template.bind({}); -Default.args = { - id: "grouptree", - data: require("../../../../../../example-data/group-tree.json"), - edge_options, -}; diff --git a/typescript/packages/group-tree/src/storybook/components/GroupTreeViewer.stories.tsx b/typescript/packages/group-tree/src/storybook/components/GroupTreeViewer.stories.tsx deleted file mode 100644 index f513e377d..000000000 --- a/typescript/packages/group-tree/src/storybook/components/GroupTreeViewer.stories.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from "react"; -import DataProvider from "../../components/DataLoader"; -import GroupTreeViewer from "../../components/GroupTreeViewer"; - -const edge_options = [ - { name: "waterrate", label: "Water Rate" }, - { name: "oilrate", label: "Oil Rate" }, - { name: "gasrate", label: "Gas Rate" }, - { name: "waterinjrate", label: "Water Injection Rate" }, - { name: "gasinjrate", label: "Gas Injection Rate" }, -]; - -const node_options = [ - { name: "pressure", label: "Pressure" }, - { name: "bhp", label: "Bottom Hole Pressure" }, -]; - -export default { - component: GroupTreeViewer, - title: "GroupTree/Components/GroupTreeViewer", - argTypes: { - id: { - description: - "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.", - }, - data: { - description: "Array of JSON objects describing group tree data.", - }, - }, -}; - -const Template = (args) => { - return ( - - - - ); -}; - -export const Default = Template.bind({}); -Default.args = { - id: "grouptree", - data: require("../../../../../../example-data/group-tree.json"), - edge_options, - node_options, -}; diff --git a/typescript/packages/group-tree/src/storybook/components/SettingsBar.stories.tsx b/typescript/packages/group-tree/src/storybook/components/SettingsBar.stories.tsx deleted file mode 100644 index b9100180d..000000000 --- a/typescript/packages/group-tree/src/storybook/components/SettingsBar.stories.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from "react"; -import DataProvider from "../../components/DataLoader"; -import SettingsBar from "../../components/Settings/SettingsBar"; - -const edge_options = [ - { name: "waterrate", label: "Water Rate" }, - { name: "oilrate", label: "Oil Rate" }, - { name: "gasrate", label: "Gas Rate" }, - { name: "waterinjrate", label: "Water Injection Rate" }, - { name: "gasinjrate", label: "Gas Injection Rate" }, -]; - -const node_options = [ - { name: "pressure", label: "Pressure" }, - { name: "bhp", label: "Bottom Hole Pressure" }, -]; - -export default { - component: SettingsBar, - title: "GroupTree/Components/SettingsBar", - argTypes: { - id: { - description: - "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.", - }, - data: { - description: "Array of JSON objects describing group tree data.", - }, - }, -}; - -const Template = (args) => { - return ( - - - - ); -}; - -export const Default = Template.bind({}); -Default.args = { - id: "grouptree", - data: require("../../../../../../example-data/group-tree.json"), - edge_options, - node_options, -}; diff --git a/typescript/packages/group-tree/src/test/TestWrapper.tsx b/typescript/packages/group-tree/src/test/TestWrapper.tsx deleted file mode 100644 index 642466018..000000000 --- a/typescript/packages/group-tree/src/test/TestWrapper.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; -import { Provider } from "react-redux"; -import { DataContext } from "../components/DataLoader"; -import { createReduxStore } from "../redux/store"; -import { testState } from "./testReduxState"; -import type { Data } from "../redux/types"; - -import exampleData from "../../../../../example-data/group-tree.json"; - -export const testStore = createReduxStore(testState); -testStore.dispatch = jest.fn() as never; - -// eslint-disable-next-line react/prop-types -export const Wrapper = ({ - children, -}: { - children: JSX.Element; -}): JSX.Element => { - return ( - - {children} - - ); -}; diff --git a/typescript/packages/group-tree/src/test/performanceMetrics.ts b/typescript/packages/group-tree/src/test/performanceMetrics.ts deleted file mode 100644 index c15bcbd72..000000000 --- a/typescript/packages/group-tree/src/test/performanceMetrics.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -const perf_metrics: any[] = []; - -const logTimes = ( - id: any, - phase: any, - actualDuration: any, - baseDuration: any -) => { - console.log( - `${id}'s phase: ${phase}\nActual time: ${actualDuration} \nBase time: ${baseDuration}` - ); - perf_metrics.push([id, phase, actualDuration, baseDuration]); -}; - -export default logTimes; -export const obj = { - perf_metrics, -}; diff --git a/typescript/packages/group-tree/src/test/testReduxState.ts b/typescript/packages/group-tree/src/test/testReduxState.ts deleted file mode 100644 index 50e312de4..000000000 --- a/typescript/packages/group-tree/src/test/testReduxState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { UISettings } from "../redux/types"; - -export const testState = { - id: "test", - ui: { - currentDateTime: "2018-02-01", - currentFlowRate: "waterrate", - currentNodeInfo: "pressure", - } as UISettings, -};