diff --git a/Src/WitsmlExplorer.Frontend/components/ContentViews/CurveValuesPlot.tsx b/Src/WitsmlExplorer.Frontend/components/ContentViews/CurveValuesPlot.tsx index 752cb8389..9943060ff 100644 --- a/Src/WitsmlExplorer.Frontend/components/ContentViews/CurveValuesPlot.tsx +++ b/Src/WitsmlExplorer.Frontend/components/ContentViews/CurveValuesPlot.tsx @@ -1,4 +1,10 @@ -import { Button, EdsProvider, Icon, Switch, Typography } from "@equinor/eds-core-react"; +import { + Button, + EdsProvider, + Icon, + Switch, + Typography +} from "@equinor/eds-core-react"; import { ThresholdLevel, transformCurveData @@ -34,8 +40,6 @@ import { Colors } from "styles/Colors"; import { normaliseThemeForEds } from "../../tools/themeHelpers.ts"; import { SettingCustomRanges } from "./SettingCustomRanges.tsx"; import { Box } from "@mui/material"; -import FilterPanel from "components/Sidebar/FilterPanel.tsx"; - const COLUMN_WIDTH = 135; const MNEMONIC_LABEL_WIDTH = COLUMN_WIDTH - 10; @@ -48,6 +52,11 @@ interface ControlledTooltipProps { content: string; } +export interface CustomCurveRange { + curve: string; + minValue: number + maxValue: number; +} interface CurveValuesPlotProps { data: any[]; columns: ExportableContentTableColumn[]; @@ -80,8 +89,10 @@ export const CurveValuesPlot = React.memo( const selectedLabels = useRef>(null); const scrollIndex = useRef(0); const horizontalZoom = useRef<[number, number]>([0, 100]); + const verticalZoom = useRef<[number, number]>([0, 100]); const [maxColumns, setMaxColumns] = useState(15); + const { width: contentViewWidth } = useContext( ContentViewDimensionsContext ); @@ -96,6 +107,10 @@ export const CurveValuesPlot = React.memo( useState({ visible: false } as ControlledTooltipProps); + + + + const transformedData = useMemo( () => transformCurveData( @@ -118,6 +133,9 @@ export const CurveValuesPlot = React.memo( } }, [contentViewWidth]); + + + const chartOption = getChartOption( transformedData, columns, @@ -132,7 +150,9 @@ export const CurveValuesPlot = React.memo( horizontalZoom.current, verticalZoom.current, isTimeLog, - enableScatter + enableScatter, + null, + customRanges ); const onMouseOver = (e: any) => { @@ -199,13 +219,10 @@ export const CurveValuesPlot = React.memo( const iconColor = colors.interactive.primaryResting; - const openCredentialsModal = () => ( - - - setExpanded(true) - - ); - + const openCredentialsModal = () => + { setExpanded(true); + console.log(columns) + } const onLegendScroll = (params: { scrollDataIndex: number }) => { scrollIndex.current = params.scrollDataIndex; }; @@ -225,8 +242,7 @@ export const CurveValuesPlot = React.memo( } }; - const handleExpandFiltersClick = () => setExpanded(!expanded); - + const handleEvents = { legendselectchanged: onLegendChange, legendscroll: onLegendScroll, @@ -235,6 +251,8 @@ export const CurveValuesPlot = React.memo( mouseout: onMouseOut }; + + return (
@@ -294,26 +312,24 @@ export const CurveValuesPlot = React.memo( Custom ranges - - -{expanded ? - - : null} + + {expanded ? ( + + + + ) : null} )} @@ -378,7 +394,9 @@ const getChartOption = ( horizontalZoom: [number, number], verticalZoom: [number, number], isTimeLog: boolean, - enableScatter: boolean + enableScatter: boolean, + minMaxVal: CustomCurveRange [], + customRange: boolean, ) => { const VALUE_OFFSET_FROM_COLUMN = 0.01; const AUTO_REFRESH_SIZE = 300; @@ -388,22 +406,22 @@ const getChartOption = ( const indexCurve = columns[0].columnOf.mnemonic; const indexUnit = columns[0].columnOf.unit; const dataColumns = columns.filter((col) => col.property != indexCurve); - const minMaxValues = columns - .map((col) => col.columnOf.mnemonic) - .map((curve) => { - const curveData = data.map((obj) => obj[curve]).filter(Number.isFinite); - return { - curve: curve, - minValue: - curveData.length == 0 - ? null - : curveData.reduce((min, v) => (min <= v ? min : v), Infinity), - maxValue: - curveData.length == 0 - ? null - : curveData.reduce((max, v) => (max >= v ? max : v), -Infinity) - }; - }); + const minMaxValues = customRange ? minMaxVal : columns + .map((col) => col.columnOf.mnemonic) + .map((curve) => { + const curveData = data.map((obj) => obj[curve]).filter(Number.isFinite); + return { + curve: curve, + minValue: + curveData.length == 0 + ? null + : curveData.reduce((min, v) => (min <= v ? min : v), Infinity), + maxValue: + curveData.length == 0 + ? null + : curveData.reduce((max, v) => (max >= v ? max : v), -Infinity) + }; + }); return { title: { diff --git a/Src/WitsmlExplorer.Frontend/components/ContentViews/SettingCustomRanges.tsx b/Src/WitsmlExplorer.Frontend/components/ContentViews/SettingCustomRanges.tsx index a906a05ba..de6455c1c 100644 --- a/Src/WitsmlExplorer.Frontend/components/ContentViews/SettingCustomRanges.tsx +++ b/Src/WitsmlExplorer.Frontend/components/ContentViews/SettingCustomRanges.tsx @@ -1,130 +1,142 @@ -import { - EdsProvider, - Icon, - Menu, - TextField, - Typography -} from "@equinor/eds-core-react"; -import { Checkbox } from "@mui/material"; -import { Column, Table } from "@tanstack/react-table"; -import { - activeId, - calculateColumnWidth, - expanderId, - selectId -} from "components/ContentViews/table/contentTableUtils"; -import { - ContentTableColumn, - ContentType -} from "components/ContentViews/table/tableParts"; -import { Button } from "components/StyledComponents/Button"; -import { UserTheme } from "contexts/operationStateReducer"; -import { useLocalStorageState } from "hooks/useLocalStorageState"; -import { useOperationState } from "hooks/useOperationState"; -import { debounce } from "lodash"; -import { ChangeEvent, useCallback, useEffect, useState } from "react"; -import { useSearchParams } from "react-router-dom"; -import { checkIsUrlTooLong } from "routes/utils/checkIsUrlTooLong"; -import styled from "styled-components"; -import { Colors } from "styles/Colors"; +import { EdsProvider, Table, TextField } from "@equinor/eds-core-react"; + +import { ExportableContentTableColumn } from "components/ContentViews/table/tableParts"; +import { useOperationState } from "hooks/useOperationState"; -type FilterValues = Record; +import { ChangeEvent, useState } from "react"; +import styled from "styled-components"; +import { colors, Colors } from "styles/Colors"; +import { CustomCurveRange } from "./CurveValuesPlot"; +import { CurveSpecification } from "models/logData"; export const SettingCustomRanges = (props: { - table: Table; + columns: ExportableContentTableColumn[]; + data: any[]; }): React.ReactElement => { - const { - operationState: { colors, theme } + operationState: { colors } } = useOperationState(); - const [isMenuOpen, setIsMenuOpen] = useState(false); - const [menuAnchor, setMenuAnchor] = useState(null); + const minMaxValuesCalculation = props.columns + .map((col) => col.columnOf.mnemonic) + .map((curve) => { + const curveData = props.data + .map((obj) => obj[curve]) + .filter(Number.isFinite); + return { + curve: curve, + minValue: + curveData.length == 0 + ? null + : curveData.reduce((min, v) => (min <= v ? min : v), Infinity), + maxValue: + curveData.length == 0 + ? null + : curveData.reduce((max, v) => (max >= v ? max : v), -Infinity) + }; + }); + const [ranges, setRanges] = useState( + minMaxValuesCalculation + ); + + const onTextFieldChange = ( + e: ChangeEvent, + index: string + ) => { + var server = ranges.find((x) => x.curve === index); + server.minValue = Number(e.target.value); + setRanges(ranges); + }; + + const onTextFieldChange2 = ( + e: ChangeEvent, + index: string + ) => { + var server = ranges.find((x) => x.curve === index); + server.maxValue = Number(e.target.value); + setRanges(ranges); + }; return ( - <> - - - setIsMenuOpen(false)} - anchorEl={menuAnchor} - placement="left-end" - colors={colors} - > - -
- - - Toggle all over - -
- {/* set onDragOver and onDrop on an outer div so that the mouse cursor properly detect a drop area, has an annoying flicker tho */} -
{ - e.preventDefault(); - }} - onDrop={(e) => { - e.preventDefault(); - }} - style={{ padding: "0.125rem 0 0.25rem 0" }} - >
-
- + + + + + + + Curve + + + + {(ranges ?? []) + .sort((a, b) => a.curve.localeCompare(b.curve)) + .map((server: CustomCurveRange) => ( + + {server.curve} + + + ) => { + onTextFieldChange(e, server.curve); + }} + /> + + ) => { + onTextFieldChange2(e, server.curve); + }} + /> + + + + ))} + +
+
+
+
); }; -const StyledMenu = styled(Menu)<{ colors: Colors }>` - background: ${(props) => props.colors.ui.backgroundLight}; - p { - color: ${(props) => props.colors.text.staticIconsDefault}; - } - padding: 0.25rem 0.5rem 0.25rem 0.5rem; - max-height: 90vh; - overflow-y: scroll; - - div[class*="InputWrapper__Container"] { - label.dHhldd { - color: ${(props) => props.colors.text.staticTextLabel}; - } - } +const StartEndIndex = styled.div` + display: flex; +`; - div[class*="Input__Container"][disabled] { - background: ${(props) => props.colors.text.staticTextFieldDefault}; - border-bottom: 1px solid #9ca6ac; - } +const CellStyle = { + color: colors.interactive.primaryResting, + padding: "0.3rem", + borderBottom: `2px solid ${colors.interactive.disabledBorder}` +}; +const CellHeaderStyle = { + ...CellStyle, + background: colors.ui.backgroundLight +}; - div[class*="Input__Container"] { - background-color: ${(props) => props.colors.text.staticTextFieldDefault}; - } +const Container = styled.div<{ colors: Colors }>` + display: flex; + flex-direction: column; + gap: 0.5em; + padding: 0.5em; + user-select: none; + box-shadow: 1px 4px 5px 0px rgba(0, 0, 0, 0.3); + background: ${(props) => props.colors.ui.backgroundLight}; +`; - input[class*="Input__StyledInput"] { - padding: 4px; - } +const InnerContainer = styled.div` + display: flex; + flex-direction: column; `; -export const createColumnFilterSearchParams = ( - currentSearchParams: URLSearchParams, - filterValues: FilterValues -): URLSearchParams => { - if (Object.entries(filterValues).length === 0) { - currentSearchParams.delete("filter"); - } else { - currentSearchParams.set("filter", JSON.stringify(filterValues)); +const StyledTextField = styled(TextField)` + div { + background-color: transparent; } - return currentSearchParams; -}; + min-width: 220px; +`;