From 4505fe49a87c706a6102c928b1a117f4c777b126 Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Thu, 4 Jul 2024 07:56:02 +0300 Subject: [PATCH 1/8] fix StrictMode; fix missed props.domain in WLV --- .../src/Storybook/ExternalLayout.stories.tsx | 2 +- .../src/SyncLogViewer.stories.tsx | 78 ++++---- .../well-log-viewer/src/SyncLogViewer.tsx | 179 ++++++++---------- .../src/WellLogViewer.stories.tsx | 7 +- .../well-log-viewer/src/WellLogViewer.tsx | 38 +++- .../components/DefaultSyncLogViewerLayout.tsx | 3 +- .../src/components/WellLogAxesPanel.tsx | 8 +- .../src/components/WellLogScaleSelector.tsx | 9 +- .../src/components/WellLogView.tsx | 10 +- .../src/components/WellLogZoomSlider.tsx | 8 +- .../well-log-viewer/src/utils/log-viewer.ts | 7 + 11 files changed, 193 insertions(+), 156 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/Storybook/ExternalLayout.stories.tsx b/typescript/packages/well-log-viewer/src/Storybook/ExternalLayout.stories.tsx index 59a0035508..7b11c3ee3e 100644 --- a/typescript/packages/well-log-viewer/src/Storybook/ExternalLayout.stories.tsx +++ b/typescript/packages/well-log-viewer/src/Storybook/ExternalLayout.stories.tsx @@ -38,7 +38,7 @@ export const RTCTabsLayout: StoryObj = { decorators: [tabDecorator], render: () => ( - , + ), }; diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx index 2c9bffaf9f..8a02208c8c 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx @@ -129,7 +129,7 @@ const stories: Meta = { }; export default stories; -function fillInfo(controller) { +function fillInfo(controller: WellLogController | undefined) { if (!controller) return "-"; const baseDomain = controller.getContentBaseDomain(); const domain = controller.getContentDomain(); @@ -158,40 +158,41 @@ function fillInfo(controller) { const Template = (args) => { const infoRef = React.useRef(); - const setInfo = function (info) { + const setInfo = function (info: string) { if (infoRef.current) infoRef.current.innerHTML = info; }; - const [controller, setController] = React.useState(null); // the first WellLog const [controllers, setControllers] = React.useState( [] ); // all WellLogs const onCreateController = React.useCallback( - (iWellLog, controller) => { - if (iWellLog === 0) setController(controller); - + (iWellLog: number, controller: WellLogController) => { setControllers((prev) => [...prev, controller]); }, - [controller] + [controllers] + ); + const onDeleteController = React.useCallback( + (iWellLog: number, controller: WellLogController) => { + setControllers((prev) => prev.filter((c) => c !== controller)); + }, + [controllers] ); const onContentRescale = React.useCallback( - (iWellLog) => { - if (iWellLog === 0) setInfo(fillInfo(controller)); + (iWellLog: number) => { + if (iWellLog === 0) setInfo(fillInfo(controllers[0])); }, - [controller] + [controllers] ); const onContentSelection = React.useCallback( (/*iWellLog*/) => { - /*if(iWellLog===0)*/ setInfo(fillInfo(controller)); + /*if(iWellLog===0)*/ setInfo(fillInfo(controllers[0])); }, - [controller] + [controllers] ); const handleClick = function () { for (const ctrl of controllers) { - if (ctrl) { - ctrl.setControllerDefaultZoom(); - } + if (ctrl) ctrl.setControllerDefaultZoom(); } }; const [checked, setChecked] = React.useState(false); @@ -216,6 +217,7 @@ const Template = (args) => { id="SyncLogViewer" {...args} onCreateController={onCreateController} + onDeleteController={onDeleteController} onContentRescale={onContentRescale} onContentSelection={onContentSelection} onTrackMouseEvent={checked ? onTrackMouseEventCustom : null} @@ -426,6 +428,8 @@ import WellLogZoomSlider from "./components/WellLogZoomSlider"; import WellLogScaleSelector from "./components/WellLogScaleSelector"; import WellInfoIcon from "@mui/icons-material/FormatListBulleted"; // WaterDrop ShowChart, SearchSharp import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward"; + +import assert from "assert"; const iconStyle = { fontSize: "18px", verticalAlign: "middle", @@ -513,7 +517,7 @@ CustomLayout.parameters = { Default.tags = ["no-screenshot-test"]; -const TemplateWithSelection = (args) => { +const TemplateWithSelection = (args: { welllogs: WellLog[] }) => { const [showWell1, setShowWell1] = React.useState(true); const [showWell2, setShowWell2] = React.useState(true); const [showWell3, setShowWell3] = React.useState(true); @@ -522,25 +526,27 @@ const TemplateWithSelection = (args) => { [] ); // all WellLogs - const onCreateController = React.useCallback((iWellLog, controller) => { - setControllers((prev) => [...prev, controller]); - }, []); + const onCreateController = React.useCallback( + (iWellLog: number, controller: WellLogController) => { + setControllers((prev) => [...prev, controller]); + }, + [] + ); + const onDeleteController = React.useCallback( + (iWellLog: number, controller: WellLogController) => { + setControllers((prev) => prev.filter((c) => c !== controller)); + }, + [] + ); const filtered: WellLog[] = []; - if (showWell1) { - filtered.push(args.welllogs[0]); - } - if (showWell2) { - filtered.push(args.welllogs[1]); - } - if (showWell3) { - filtered.push(args.welllogs[2]); - } + if (showWell1 && args.welllogs[0]) filtered.push(args.welllogs[0]); + if (showWell2 && args.welllogs[1]) filtered.push(args.welllogs[1]); + if (showWell3 && args.welllogs[2]) filtered.push(args.welllogs[2]); + const handleClick = function () { for (const ctrl of controllers) { - if (ctrl) { - ctrl.setControllerDefaultZoom(); - } + if (ctrl) ctrl.setControllerDefaultZoom(); } }; @@ -556,8 +562,9 @@ const TemplateWithSelection = (args) => {
{ + if (!args.welllogs[0]) assert("!args.welllogs[0]"); setShowWell1(!showWell1); }} > @@ -565,8 +572,9 @@ const TemplateWithSelection = (args) => { { + if (!args.welllogs[1]) alert("!args.welllogs[1]"); setShowWell2(!showWell2); }} > @@ -574,8 +582,9 @@ const TemplateWithSelection = (args) => { { + if (!args.welllogs[2]) alert("!args.welllogs[2]"); setShowWell3(!showWell3); }} > @@ -590,6 +599,7 @@ const TemplateWithSelection = (args) => { id="SyncLogViewer" {...argsWithSelection} onCreateController={onCreateController} + onDeleteController={onDeleteController} />
diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx index 4d9e601a2d..e562d7a942 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx @@ -171,6 +171,10 @@ export interface SyncLogViewerProps { iWellLog: number, controller: WellLogController ) => void; + onDeleteController?: ( + iWellLog: number, + controller: WellLogController + ) => void; } export const argTypesSyncLogViewerProp = { @@ -276,6 +280,8 @@ class SyncLogViewer extends Component { onTemplateChangedBind: () => void; }[]; + controllers: WellLogController[]; // for onDeletecontroller implementation + _isMounted: boolean; _inInfoGroupClick: number; @@ -287,20 +293,21 @@ class SyncLogViewer extends Component { this.callbacks = []; this.callbackManagers = []; + this.controllers = []; + this._isMounted = false; this._inInfoGroupClick = 0; - const primaryAxis = this.getDefaultPrimaryAxis(); - this.state = { - primaryAxis: primaryAxis, //"md" + primaryAxis: this.getDefaultPrimaryAxis(), //"md" }; this.onChangePrimaryAxis = this.onChangePrimaryAxis.bind(this); - - this.fillViewsCallbacks(this.props.welllogs.length); } componentDidMount(): void { + this._isMounted = true; + this.fillViewsCallbacks(this.props.welllogs.length); + if (this.props.welllogs.length) { this.syncTrackScrollPos(0); this.syncContentScrollPos(0); @@ -310,7 +317,6 @@ class SyncLogViewer extends Component { this.setControllersZoom(); } if (this.props.welllogs.length) this.syncContentSelection(0); - this._isMounted = true; } componentWillUnmount(): void { @@ -330,41 +336,25 @@ class SyncLogViewer extends Component { return ret; } - UNSAFE_componentWillUpdate( - nextProps: SyncLogViewerProps /*, nextState: State*/ - ): void { - // called before render() - if (this.props.welllogs.length === nextProps.welllogs.length) return; - if (this.callbackManagers.length === nextProps.welllogs.length) return; + beforeRender(): void { + // Are we adding new items to the list? + // Capture the scroll position so we can adjust scroll later. /* - // move old controllers to new places in the controllers array - const controllers: (WellLogController | null)[] = []; - const spacers: (WellLogSpacer | null)[] = []; - for (const wellLog of nextProps.welllogs) { - const index = this.controllers.findIndex( - (controller) => controller?.getWellLog() === wellLog - ); - if (index < 0) { - controllers.push(null); - spacers.push(null); - } - else { - controllers.push(this.controllers.splice(index, 1)[0]); - spacers.push(this.spacers.splice(index, 1)[0]); - } + if (prevProps.list.length < this.props.list.length) { + const list = this.listRef.current; + return list.scrollHeight - list.scrollTop; } - this.controllers = controllers; - this.spacers = spacers; */ - // just resize arrays - - this.spacers.length = nextProps.welllogs.length; + // called before render() + //if (prevProps.welllogs.length === this.props.welllogs.length) return; + if (this.callbackManagers.length === this.props.welllogs.length) return; + this.spacers.length = this.props.welllogs.length; - this.fillViewsCallbacks(nextProps.welllogs.length); // update this.callbackManagers and this.callbacks[] before render() + this.fillViewsCallbacks(this.props.welllogs.length); // update this.callbackManagers and this.callbacks[] before render() } componentDidUpdate( - prevProps: SyncLogViewerProps /*, prevState: State*/ + prevProps: SyncLogViewerProps /*, prevState: State, snapshot*/ ): void { if ( this.props.welllogs !== prevProps.welllogs || @@ -372,10 +362,8 @@ class SyncLogViewer extends Component { this.props.axisMnemos !== prevProps.axisMnemos || this.props.primaryAxis !== prevProps.primaryAxis ) { - const primaryAxis = this.getAxes().primaryAxis; - this.setState({ - primaryAxis: primaryAxis, - }); + const value = this.getDefaultPrimaryAxis(); + this.onChangePrimaryAxis(value); } if ( @@ -409,30 +397,6 @@ class SyncLogViewer extends Component { } } - getPrimaryAxis(axes: string[]): string { - if (axes) { - const template0 = this.props.templates[0]; - if (template0) { - const scale = template0.scale; - if (scale) { - const primary = scale.primary; - if (axes.indexOf(primary) >= 0) return primary; - } - } - return axes[0]; - } - return "tvd"; // some value - } - - getAxes() { - const _axes = this.props.welllogs.map((welllog: WellLog) => - getAvailableAxes(welllog, this.props.axisMnemos) - ); - const axes = _axes[0]; - const primaryAxis = this.props.primaryAxis || this.getPrimaryAxis(axes); - return { axes, primaryAxis }; - } - fillViewCallbacks(iView: number): void { const callbackManager = new CallbackManager( () => this.props.welllogs[iView] @@ -460,25 +424,37 @@ class SyncLogViewer extends Component { this.fillViewCallbacks(iView); this.callbacks.length = nViews; this.callbackManagers.length = nViews; + + /*for (let iView = nViews; iView < this.controllers.length; iView++) { + console.assert(this.controllers[iView]); + this.onDeleteController(iView,this.controllers[iView]); + }*/ + this.controllers.length = nViews; + } + + getPrimaryAxis(): string { + return this.state.primaryAxis; } getDefaultPrimaryAxis(): string { + if (this.props.primaryAxis) return this.props.primaryAxis; + const _axes = this.props.welllogs?.map((welllog: WellLog) => getAvailableAxes(welllog, this.props.axisMnemos) ); const axes = _axes?.[0]; let primaryAxis = axes?.[0]; - if (this.props.templates) { - const template = this.props.templates[0]; - if (template) { - template.scale.primary = "tvd"; //!!!!! - if (template.scale.primary && axes) { - if (axes.indexOf(template.scale.primary) >= 0) - primaryAxis = template.scale.primary; + const template = this.props.templates?.[0]; + if (template) { + const scale = template.scale; + if (scale) { + let primary = scale.primary; + if (!primary) primary = "tvd"; //!!!!! + if (primary && axes) { + if (axes.indexOf(primary) >= 0) primaryAxis = primary; } } } - if (this.props.primaryAxis) primaryAxis = this.props.primaryAxis; return primaryAxis; } @@ -496,7 +472,7 @@ class SyncLogViewer extends Component { // callback function from WellLogView onCreateController(iWellLog: number, controller: WellLogController): void { - this.callbackManagers[iWellLog].onCreateController(controller); + this.callbackManagers[iWellLog]?.onCreateController(controller); // set callback to component's caller this.props.onCreateController?.(iWellLog, controller); @@ -504,6 +480,11 @@ class SyncLogViewer extends Component { this.syncTrackScrollPos(iWellLog); this.syncContentScrollPos(iWellLog); this.syncContentSelection(iWellLog); + + this.controllers[iWellLog] = controller; + } + onDeleteController(iWellLog: number, controller: WellLogController): void { + this.props.onDeleteController?.(iWellLog, controller); } // callback function from WellLogView onTrackScroll(iWellLog: number): void { @@ -525,14 +506,14 @@ class SyncLogViewer extends Component { } // callback function from WellLogView onContentSelection(iWellLog: number): void { - this.callbackManagers[iWellLog].onContentSelection(); + this.callbackManagers[iWellLog]?.onContentSelection(); this.syncContentSelection(iWellLog); this.props.onContentSelection?.(iWellLog); } // callback function from WellLogView onTemplateChanged(iWellLog: number): void { - this.callbackManagers[iWellLog].onTemplateChanged(); + this.callbackManagers[iWellLog]?.onTemplateChanged(); this.syncTemplate(iWellLog); @@ -901,6 +882,7 @@ class SyncLogViewer extends Component { selection={this.props.selection} primaryAxis={this.state.primaryAxis} options={options} + // callbacks onInfo={callbackManager.onInfo} onCreateController={callbacks.onCreateControllerBind} onTrackMouseEvent={ @@ -972,31 +954,34 @@ class SyncLogViewer extends Component { } render(): JSX.Element { + this.beforeRender(); return ( - - {this.props.welllogs?.map( - (_welllog: WellLog, index: number) => [ - index ? this.createSpacer(index) : null, - this.createView(index), - ] - )} - - } - layout={this.props.layout || defaultLayout} - /> + + + {this.props.welllogs?.map( + (_welllog: WellLog, index: number) => [ + index ? this.createSpacer(index) : null, + this.createView(index), + ] + )} + + } + layout={this.props.layout || defaultLayout} + /> + ); } } diff --git a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx index 390ce78b6c..6db6c0c8d1 100644 --- a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx @@ -4,6 +4,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import React from "react"; import WellLogViewer, { argTypesWellLogViewerProp } from "./WellLogViewer"; +import type { WellLogController } from "./components/WellLogView"; import exampleData from "../../../../example-data/deckgl-map.json"; @@ -86,7 +87,7 @@ const stories: Meta = { }; export default stories; -function fillInfo(controller) { +function fillInfo(controller: WellLogController | undefined) { if (!controller) return "-"; const baseDomain = controller.getContentBaseDomain(); const domain = controller.getContentDomain(); @@ -118,7 +119,9 @@ const StoryTemplate = (args) => { const setInfo = function (info) { if (infoRef.current) infoRef.current.innerHTML = info; }; - const [controller, setController] = React.useState(null); + const [controller, setController] = React.useState< + WellLogController | undefined + >(undefined); const onCreateController = React.useCallback( (controller) => { setController(controller); diff --git a/typescript/packages/well-log-viewer/src/WellLogViewer.tsx b/typescript/packages/well-log-viewer/src/WellLogViewer.tsx index b8d737227c..e57ee4edfa 100644 --- a/typescript/packages/well-log-viewer/src/WellLogViewer.tsx +++ b/typescript/packages/well-log-viewer/src/WellLogViewer.tsx @@ -115,11 +115,17 @@ export default class WellLogViewer extends Component< } // callback function from Axis selector onChangePrimaryAxis(value: string): void { + this.setState({ primaryAxis: value }); this.callbackManager.onChangePrimaryAxis(value); } componentDidMount(): void { this.onContentRescale(); + const controller = this.callbackManager?.controller; + if (controller) { + const trackPos = controller.getTrackScrollPos(); + controller.scrollTrackTo(trackPos); + } } componentWillUnmount(): void { @@ -147,9 +153,8 @@ export default class WellLogViewer extends Component< this.props.axisMnemos !== prevProps.axisMnemos || this.props.primaryAxis !== prevProps.primaryAxis ) { - this.setState({ - primaryAxis: this.getDefaultPrimaryAxis(), - }); + const value = this.getDefaultPrimaryAxis(); + this.onChangePrimaryAxis(value); } } @@ -157,16 +162,24 @@ export default class WellLogViewer extends Component< return this.state.primaryAxis; } getDefaultPrimaryAxis(): string { + if (this.props.primaryAxis) return this.props.primaryAxis; + const axes = getAvailableAxes( this.props.welllog, this.props.axisMnemos ); let primaryAxis = axes[0]; - if (this.props.template && this.props.template.scale.primary) { - if (axes.indexOf(this.props.template.scale.primary) >= 0) - primaryAxis = this.props.template.scale.primary; + const template = this.props.template; + if (template) { + const scale = template.scale; + if (scale) { + let primary = scale.primary; + if (!primary) primary = "tvd"; //!!!!! + if (primary && axes) { + if (axes.indexOf(primary) >= 0) primaryAxis = primary; + } + } } - if (this.props.primaryAxis) primaryAxis = this.props.primaryAxis; return primaryAxis; } @@ -177,21 +190,26 @@ export default class WellLogViewer extends Component< center={ diff --git a/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx b/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx index 9c6fe8fcee..64f7956236 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx @@ -50,15 +50,19 @@ export class WellLogAxesPanel extends Component { }; this.onChangePrimaryAxis = this.onChangePrimaryAxis.bind(this); + } - this.props.callbackManager.registerCallback( + componentDidMount(): void { + const callbackManager = this.props.callbackManager; + callbackManager?.registerCallback( "onChangePrimaryAxis", this.onChangePrimaryAxis ); } componentWillUnmount(): void { - this.props.callbackManager.unregisterCallback( + const callbackManager = this.props.callbackManager; + callbackManager.unregisterCallback( "onChangePrimaryAxis", this.onChangePrimaryAxis ); diff --git a/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx b/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx index db1833f462..99563362b7 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx @@ -25,13 +25,18 @@ export class WellLogScaleSelector extends Component { this.onChange = this.onChange.bind(this); this.onContentRescale = this.onContentRescale.bind(this); - this.props.callbackManager?.registerCallback( + } + componentDidMount(): void { + const callbackManager = this.props.callbackManager; + callbackManager?.registerCallback( "onContentRescale", this.onContentRescale ); } + componentWillUnmount(): void { - this.props.callbackManager?.unregisterCallback( + const callbackManager = this.props.callbackManager; + callbackManager?.unregisterCallback( "onContentRescale", this.onContentRescale ); diff --git a/typescript/packages/well-log-viewer/src/components/WellLogView.tsx b/typescript/packages/well-log-viewer/src/components/WellLogView.tsx index 2f51d7f7f3..975a697a3a 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogView.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogView.tsx @@ -947,6 +947,8 @@ export interface WellLogController { getTemplate(): Template; getWellLog(): WellLog | undefined; + + setControllerDefaultZoom(): void; // utility function } export function getContentBaseScale( @@ -1309,21 +1311,21 @@ class WellLogView // set callback to component's caller this.props.onCreateController?.(this); - this.setControllerZoom(); - this._isMount = false; } componentDidMount(): void { + if (this._isMount) return; // anti-StrictMode workaround + + this._isMount = true; this.createLogViewer(); this.template = deepCopy(this.props.template); // save external template content to current this.setTracks(true); - - this._isMount = true; } componentWillUnmount(): void { + if (this._isMount) return; // anti-StrictMode workaround this._isMount = false; } diff --git a/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx b/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx index 1400d8a01d..991c3780b7 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx @@ -23,15 +23,19 @@ export class WellLogZoomSlider extends Component { this.onContentRescale = this.onContentRescale.bind(this); this.onZoomSliderChange = this.onZoomSliderChange.bind(this); + } - this.props.callbackManager?.registerCallback( + componentDidMount(): void { + const callbackManager = this.props.callbackManager; + callbackManager?.registerCallback( "onContentRescale", this.onContentRescale ); } componentWillUnmount(): void { - this.props.callbackManager?.unregisterCallback( + const callbackManager = this.props.callbackManager; + callbackManager?.unregisterCallback( "onContentRescale", this.onContentRescale ); diff --git a/typescript/packages/well-log-viewer/src/utils/log-viewer.ts b/typescript/packages/well-log-viewer/src/utils/log-viewer.ts index 55d3566cb1..7b5a5fed32 100644 --- a/typescript/packages/well-log-viewer/src/utils/log-viewer.ts +++ b/typescript/packages/well-log-viewer/src/utils/log-viewer.ts @@ -19,6 +19,13 @@ export function isEqDomains( d1: Domain /*[number, number]*/, d2: Domain /*[number, number]*/ ): boolean { + if ( + Number.isNaN(d1[1]) && + Number.isNaN(d1[0]) && + Number.isNaN(d2[1]) && + Number.isNaN(d2[0]) + ) + return true; const eps: number = Math.abs(d1[1] - d1[0] + (d2[1] - d2[0])) * 0.00001; return Math.abs(d1[0] - d2[0]) < eps && Math.abs(d1[1] - d2[1]) < eps; } From 49ffb180aa665636c69c404dc87458dba896379c Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Thu, 4 Jul 2024 08:58:55 +0300 Subject: [PATCH 2/8] remove development --- .../well-log-viewer/src/SyncLogViewer.tsx | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx index e562d7a942..1302defab1 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx @@ -425,10 +425,10 @@ class SyncLogViewer extends Component { this.callbacks.length = nViews; this.callbackManagers.length = nViews; - /*for (let iView = nViews; iView < this.controllers.length; iView++) { + for (let iView = nViews; iView < this.controllers.length; iView++) { console.assert(this.controllers[iView]); - this.onDeleteController(iView,this.controllers[iView]); - }*/ + this.onDeleteController(iView, this.controllers[iView]); + } this.controllers.length = nViews; } @@ -956,32 +956,30 @@ class SyncLogViewer extends Component { render(): JSX.Element { this.beforeRender(); return ( - - - {this.props.welllogs?.map( - (_welllog: WellLog, index: number) => [ - index ? this.createSpacer(index) : null, - this.createView(index), - ] - )} - - } - layout={this.props.layout || defaultLayout} - /> - + + {this.props.welllogs?.map( + (_welllog: WellLog, index: number) => [ + index ? this.createSpacer(index) : null, + this.createView(index), + ] + )} + + } + layout={this.props.layout || defaultLayout} + /> ); } } From ca7273800e83a67a4d093a471c9f5ca57258a5c3 Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:05:59 +0300 Subject: [PATCH 3/8] remove unnessesary comments --- .../packages/well-log-viewer/src/SyncLogViewer.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx index 1302defab1..67ba799b77 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx @@ -337,16 +337,7 @@ class SyncLogViewer extends Component { } beforeRender(): void { - // Are we adding new items to the list? - // Capture the scroll position so we can adjust scroll later. - /* - if (prevProps.list.length < this.props.list.length) { - const list = this.listRef.current; - return list.scrollHeight - list.scrollTop; - } - */ // called before render() - //if (prevProps.welllogs.length === this.props.welllogs.length) return; if (this.callbackManagers.length === this.props.welllogs.length) return; this.spacers.length = this.props.welllogs.length; From 3ad24bb2176c84395c2874953a69523bee412fc9 Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Thu, 4 Jul 2024 20:36:21 +0300 Subject: [PATCH 4/8] finish onDeleteController callback --- .../src/SyncLogViewer.stories.tsx | 11 +++++------ .../well-log-viewer/src/SyncLogViewer.tsx | 16 +++++++++------- .../src/components/WellLogAxesPanel.tsx | 2 +- .../src/components/WellLogInfoPanel.tsx | 2 +- .../src/components/WellLogView.tsx | 11 +++++------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx index 8a02208c8c..5a8ff30603 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx @@ -170,13 +170,13 @@ const Template = (args) => { (iWellLog: number, controller: WellLogController) => { setControllers((prev) => [...prev, controller]); }, - [controllers] + [] ); const onDeleteController = React.useCallback( (iWellLog: number, controller: WellLogController) => { setControllers((prev) => prev.filter((c) => c !== controller)); }, - [controllers] + [] ); const onContentRescale = React.useCallback( (iWellLog: number) => { @@ -429,7 +429,6 @@ import WellLogScaleSelector from "./components/WellLogScaleSelector"; import WellInfoIcon from "@mui/icons-material/FormatListBulleted"; // WaterDrop ShowChart, SearchSharp import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward"; -import assert from "assert"; const iconStyle = { fontSize: "18px", verticalAlign: "middle", @@ -564,7 +563,7 @@ const TemplateWithSelection = (args: { welllogs: WellLog[] }) => { value="check" selected={showWell1 && !!args.welllogs[0]} onChange={() => { - if (!args.welllogs[0]) assert("!args.welllogs[0]"); + if (!args.welllogs[1]) alert("No args.welllogs[0]"); setShowWell1(!showWell1); }} > @@ -574,7 +573,7 @@ const TemplateWithSelection = (args: { welllogs: WellLog[] }) => { value="check" selected={showWell2 && !!args.welllogs[1]} onChange={() => { - if (!args.welllogs[1]) alert("!args.welllogs[1]"); + if (!args.welllogs[1]) alert("No args.welllogs[1]"); setShowWell2(!showWell2); }} > @@ -584,7 +583,7 @@ const TemplateWithSelection = (args: { welllogs: WellLog[] }) => { value="check" selected={showWell3 && !!args.welllogs[2]} onChange={() => { - if (!args.welllogs[2]) alert("!args.welllogs[2]"); + if (!args.welllogs[2]) alert("No args.welllogs[2]"); setShowWell3(!showWell3); }} > diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx index 67ba799b77..c5bca2e502 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.tsx @@ -303,10 +303,11 @@ class SyncLogViewer extends Component { }; this.onChangePrimaryAxis = this.onChangePrimaryAxis.bind(this); + + this.beforeRender(this.props); } componentDidMount(): void { this._isMounted = true; - this.fillViewsCallbacks(this.props.welllogs.length); if (this.props.welllogs.length) { this.syncTrackScrollPos(0); @@ -333,15 +334,17 @@ class SyncLogViewer extends Component { const ret = !Object.is(this.props, nextProps) || !Object.is(this.state, nextState); + + if (ret) this.beforeRender(nextProps); return ret; } - beforeRender(): void { - // called before render() - if (this.callbackManagers.length === this.props.welllogs.length) return; - this.spacers.length = this.props.welllogs.length; + beforeRender(props: SyncLogViewerProps): void { + // called before render() but not inside it to avoid onDeleteController notifications + if (this.callbackManagers.length === props.welllogs.length) return; + this.spacers.length = props.welllogs.length; - this.fillViewsCallbacks(this.props.welllogs.length); // update this.callbackManagers and this.callbacks[] before render() + this.fillViewsCallbacks(props.welllogs.length); // update this.callbackManagers and this.callbacks[] before render() } componentDidUpdate( @@ -945,7 +948,6 @@ class SyncLogViewer extends Component { } render(): JSX.Element { - this.beforeRender(); return ( { componentWillUnmount(): void { const callbackManager = this.props.callbackManager; - callbackManager.unregisterCallback( + callbackManager?.unregisterCallback( "onChangePrimaryAxis", this.onChangePrimaryAxis ); diff --git a/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx b/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx index c310882a60..2a300a87ee 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx @@ -58,7 +58,7 @@ export class WellLogInfoPanel extends Component { true ); - this.props.callbackManager.updateInfo(); // force onInfo callback to be called + callbackManager.updateInfo(); // force onInfo callback to be called } componentWillUnmount(): void { diff --git a/typescript/packages/well-log-viewer/src/components/WellLogView.tsx b/typescript/packages/well-log-viewer/src/components/WellLogView.tsx index 975a697a3a..bf4f426e1b 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogView.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogView.tsx @@ -1315,17 +1315,16 @@ class WellLogView } componentDidMount(): void { - if (this._isMount) return; // anti-StrictMode workaround - this._isMount = true; - this.createLogViewer(); - this.template = deepCopy(this.props.template); // save external template content to current - this.setTracks(true); + + if (!this.logController) { + this.createLogViewer(); + this.setTracks(true); + } } componentWillUnmount(): void { - if (this._isMount) return; // anti-StrictMode workaround this._isMount = false; } From 5cc792bc48754306290e8dca282e068d50067a65 Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:10:14 +0300 Subject: [PATCH 5/8] Update WellLogViewer.stories.tsx --- .../src/WellLogViewer.stories.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx index bc12a33d6d..b1b9288dd9 100644 --- a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx @@ -106,11 +106,11 @@ function fillInfo(controller: WellLogController | undefined) { "]" + (selection[0] !== undefined ? ", selected: [" + - selection[0].toFixed(0) + - (selection[1] !== undefined - ? ", " + selection[1].toFixed(0) - : "") + - "]" + selection[0].toFixed(0) + + (selection[1] !== undefined + ? ", " + selection[1].toFixed(0) + : "") + + "]" : "") ); } @@ -507,12 +507,12 @@ class MapAndWellLogViewer extends React.Component { style={{ color: wellColor ? "rgb(" + - wellColor[0] + - "," + - wellColor[1] + - "," + - wellColor[2] + - ")" + wellColor[0] + + "," + + wellColor[1] + + "," + + wellColor[2] + + ")" : undefined, fontSize: "small", }} From 38599b65dc7e0952e34a755ef932e5743b108c9f Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:21:56 +0300 Subject: [PATCH 6/8] fix compiler error --- .../packages/well-log-viewer/src/SyncLogViewer.stories.tsx | 2 +- .../packages/well-log-viewer/src/WellLogViewer.stories.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx index 5a8ff30603..bc74f4241e 100644 --- a/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/SyncLogViewer.stories.tsx @@ -10,8 +10,8 @@ const wellpick = require("../../../../example-data/wellpicks.json");// eslint-di import { ToggleButton } from "@mui/material"; import SyncLogViewer, { argTypesSyncLogViewerProp } from "./SyncLogViewer"; -import type WellLogView from "./components/WellLogView"; import type { + WellLogView, WellLogController, TrackMouseEvent, } from "./components/WellLogView"; diff --git a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx index b1b9288dd9..638fa639dc 100644 --- a/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx +++ b/typescript/packages/well-log-viewer/src/WellLogViewer.stories.tsx @@ -4,7 +4,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import React from "react"; import WellLogViewer, { argTypesWellLogViewerProp } from "./WellLogViewer"; -import type { WellLogController } from "./components/WellLogView"; import exampleData from "../../../../example-data/deckgl-map.json"; From ce81bff3f8e13d061a6a3949f95404eb9fdb24df Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:22:05 +0300 Subject: [PATCH 7/8] Fix registering callbacks to CallbackManager --- .../src/components/WellLogAxesPanel.tsx | 20 ++++++++--- .../src/components/WellLogInfoPanel.tsx | 35 +++++++++++++------ .../src/components/WellLogScaleSelector.tsx | 22 +++++++++--- .../src/components/WellLogZoomSlider.tsx | 21 ++++++++--- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx b/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx index c989968de3..1bc7f78684 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogAxesPanel.tsx @@ -52,23 +52,33 @@ export class WellLogAxesPanel extends Component { this.onChangePrimaryAxis = this.onChangePrimaryAxis.bind(this); } - componentDidMount(): void { - const callbackManager = this.props.callbackManager; + registerCallbacks(callbackManager: CallbackManager): void { callbackManager?.registerCallback( "onChangePrimaryAxis", this.onChangePrimaryAxis ); } - - componentWillUnmount(): void { - const callbackManager = this.props.callbackManager; + unregisterCallbacks(callbackManager: CallbackManager): void { callbackManager?.unregisterCallback( "onChangePrimaryAxis", this.onChangePrimaryAxis ); } + componentDidMount(): void { + this.registerCallbacks(this.props.callbackManager); + } + + componentWillUnmount(): void { + this.unregisterCallbacks(this.props.callbackManager); + } + componentDidUpdate(prevProps: Props): void { + if (prevProps.callbackManager !== this.props.callbackManager) { + this.unregisterCallbacks(prevProps.callbackManager); + this.registerCallbacks(this.props.callbackManager); + } + const wellog = this.props.callbackManager?.welllog(); if ( this.welllog !== wellog || diff --git a/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx b/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx index 2a300a87ee..309fd81edf 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogInfoPanel.tsx @@ -29,7 +29,7 @@ function toggleId( } export class WellLogInfoPanel extends Component { - onGroupClick: (info: Info) => void; + onGroupClick?: (info: Info) => void; collapsedTrackIds: (string | number)[]; constructor(props: Props) { @@ -41,28 +41,25 @@ export class WellLogInfoPanel extends Component { this.onInfo = this.onInfo.bind(this); this.onInfoGroupClick = this.onInfoGroupClick.bind(this); + this.onGroupClick = undefined; + } - const callbackManager = this.props.callbackManager; + registerCallBacks(callbackManager: CallbackManager | undefined): void { + if (!callbackManager) return; this.onGroupClick = callbackManager.callCallbacks.bind( callbackManager, "onInfoGroupClick" ); - } - - componentDidMount(): void { - const callbackManager = this.props.callbackManager; callbackManager.registerCallback("onInfo", this.onInfo); callbackManager.registerCallback( "onInfoGroupClick", this.onInfoGroupClick, true ); - - callbackManager.updateInfo(); // force onInfo callback to be called } - - componentWillUnmount(): void { - const callbackManager = this.props.callbackManager; + unregisterCallBacks(callbackManager: CallbackManager | undefined): void { + if (!callbackManager) return; + this.onGroupClick = undefined; callbackManager.unregisterCallback("onInfo", this.onInfo); callbackManager.unregisterCallback( "onInfoGroupClick", @@ -70,7 +67,23 @@ export class WellLogInfoPanel extends Component { ); } + componentDidMount(): void { + const callbackManager = this.props.callbackManager; + this.registerCallBacks(callbackManager); + + callbackManager.updateInfo(); // force onInfo callback to be called + } + + componentWillUnmount(): void { + const callbackManager = this.props.callbackManager; + this.unregisterCallBacks(callbackManager); + } + componentDidUpdate(prevProps: Props /*, prevState: State*/): void { + if (prevProps.callbackManager !== this.props.callbackManager) { + this.unregisterCallBacks(prevProps.callbackManager); + this.registerCallBacks(this.props.callbackManager); + } if ( this.props.readoutOptions && (!prevProps.readoutOptions || diff --git a/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx b/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx index 99563362b7..6fd76cf445 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogScaleSelector.tsx @@ -26,22 +26,36 @@ export class WellLogScaleSelector extends Component { this.onChange = this.onChange.bind(this); this.onContentRescale = this.onContentRescale.bind(this); } - componentDidMount(): void { - const callbackManager = this.props.callbackManager; + + registerCallbacks(callbackManager: CallbackManager | undefined): void { callbackManager?.registerCallback( "onContentRescale", this.onContentRescale ); } - componentWillUnmount(): void { - const callbackManager = this.props.callbackManager; + unregisterCallbacks(callbackManager: CallbackManager | undefined): void { callbackManager?.unregisterCallback( "onContentRescale", this.onContentRescale ); } + componentDidMount(): void { + this.registerCallbacks(this.props.callbackManager); + } + + componentWillUnmount(): void { + this.unregisterCallbacks(this.props.callbackManager); + } + + componentDidUpdate(prevProps: Props): void { + if (prevProps.callbackManager !== this.props.callbackManager) { + this.unregisterCallbacks(prevProps.callbackManager); + this.registerCallbacks(this.props.callbackManager); + } + } + // callback function from Vertical Scale combobox onChange(value: number): void { const controller = this.props.callbackManager?.controller; diff --git a/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx b/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx index 991c3780b7..ff76818720 100644 --- a/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx +++ b/typescript/packages/well-log-viewer/src/components/WellLogZoomSlider.tsx @@ -25,22 +25,35 @@ export class WellLogZoomSlider extends Component { this.onZoomSliderChange = this.onZoomSliderChange.bind(this); } - componentDidMount(): void { - const callbackManager = this.props.callbackManager; + registerCallbacks(callbackManager: CallbackManager | undefined): void { callbackManager?.registerCallback( "onContentRescale", this.onContentRescale ); } - componentWillUnmount(): void { - const callbackManager = this.props.callbackManager; + unregisterCallbacks(callbackManager: CallbackManager | undefined): void { callbackManager?.unregisterCallback( "onContentRescale", this.onContentRescale ); } + componentDidMount(): void { + this.registerCallbacks(this.props.callbackManager); + } + + componentWillUnmount(): void { + this.unregisterCallbacks(this.props.callbackManager); + } + + componentDidUpdate(prevProps: Props): void { + if (prevProps.callbackManager !== this.props.callbackManager) { + this.unregisterCallbacks(prevProps.callbackManager); + this.registerCallbacks(this.props.callbackManager); + } + } + onContentRescale(): void { this.setState((state: Readonly) => { const controller = this.props.callbackManager?.controller; From f2e66ebae4a7d2b6ae010aa99b8fea2957be8b56 Mon Sep 17 00:00:00 2001 From: Vladimir-Kokin <86053741+Vladimir-Kokin@users.noreply.github.com> Date: Thu, 11 Jul 2024 13:01:32 +0300 Subject: [PATCH 8/8] let's assume all invalid domains are equivalent --- .../packages/well-log-viewer/src/utils/log-viewer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/typescript/packages/well-log-viewer/src/utils/log-viewer.ts b/typescript/packages/well-log-viewer/src/utils/log-viewer.ts index 7b5a5fed32..a50505fc48 100644 --- a/typescript/packages/well-log-viewer/src/utils/log-viewer.ts +++ b/typescript/packages/well-log-viewer/src/utils/log-viewer.ts @@ -20,12 +20,12 @@ export function isEqDomains( d2: Domain /*[number, number]*/ ): boolean { if ( - Number.isNaN(d1[1]) && - Number.isNaN(d1[0]) && - Number.isNaN(d2[1]) && + Number.isNaN(d1[1]) || + Number.isNaN(d1[0]) || + Number.isNaN(d2[1]) || Number.isNaN(d2[0]) ) - return true; + return true; // let's assume all invalid domains are equivalent const eps: number = Math.abs(d1[1] - d1[0] + (d2[1] - d2[0])) * 0.00001; return Math.abs(d1[0] - d2[0]) < eps && Math.abs(d1[1] - d2[1]) < eps; }