From 08ca5bd10bea257f081f638263778b3407e3cc9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= <70905152+haakonflatval-cognite@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:28:34 +0200 Subject: [PATCH 1/6] chore(react-components): bump to 0.58.1 (#4751) --- react-components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-components/package.json b/react-components/package.json index 6618d27c9ff..7ab156a1568 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -1,6 +1,6 @@ { "name": "@cognite/reveal-react-components", - "version": "0.58.0", + "version": "0.58.1", "exports": { ".": { "import": "./dist/index.js", From a14dfad0e3ba5f627551ba2272598e9724b3d29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= <70905152+haakonflatval-cognite@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:33:37 +0200 Subject: [PATCH 2/6] fix(react-components): don't send CAD connections request without items (#4752) --- .../core-dm-provider/getCadConnectionsForRevisions.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/react-components/src/data-providers/core-dm-provider/getCadConnectionsForRevisions.ts b/react-components/src/data-providers/core-dm-provider/getCadConnectionsForRevisions.ts index 5649a16501a..252a20e8545 100644 --- a/react-components/src/data-providers/core-dm-provider/getCadConnectionsForRevisions.ts +++ b/react-components/src/data-providers/core-dm-provider/getCadConnectionsForRevisions.ts @@ -24,6 +24,9 @@ export async function getCadConnectionsForRevisions( modelRevisions: Array<[DmsUniqueIdentifier, DmsUniqueIdentifier]>, fdmSdk: FdmSDK ): Promise { + if (modelRevisions.length === 0) { + return []; + } const results = await getModelConnectionResults(modelRevisions, fdmSdk); const object3dToAssetMap = createObject3dToAssetMap(results.items.assets); const cadNodeToModelMap = createCadNodeToObject3dMap(results.items.cad_nodes); From a326ffea79df84fcb26520243722c28b6f16fea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= <70905152+haakonflatval-cognite@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:51:10 +0200 Subject: [PATCH 3/6] fix(react-components): update model when geometry filter changed (#4753) * fix(react-components): update model when geometry filter changed * Revert "fix(react-components): update model when geometry filter changed" This reverts commit 5466ca5566d02f9047c15d2e05a766c39a58cfe5. * fix: do the check otherwise, to avoid too much add/remove * chore: be more strict in the add/remove-logic It's a miracle this worked before * chore: lint fix --- .../CadModelContainer/CadModelContainer.tsx | 23 ++++++++++++------- react-components/src/utilities/isSameModel.ts | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/react-components/src/components/CadModelContainer/CadModelContainer.tsx b/react-components/src/components/CadModelContainer/CadModelContainer.tsx index d36323f2fd8..154f54b812b 100644 --- a/react-components/src/components/CadModelContainer/CadModelContainer.tsx +++ b/react-components/src/components/CadModelContainer/CadModelContainer.tsx @@ -2,9 +2,9 @@ * Copyright 2023 Cognite AS */ import { type ReactElement, useEffect, useState, useRef } from 'react'; -import { type AddModelOptions, type CogniteCadModel } from '@cognite/reveal'; +import { type GeometryFilter, type AddModelOptions, type CogniteCadModel } from '@cognite/reveal'; import { useReveal } from '../RevealCanvas/ViewerContext'; -import { Matrix4 } from 'three'; +import { type Matrix4 } from 'three'; import { useRevealKeepAlive } from '../RevealKeepAlive/RevealKeepAliveContext'; import { useReveal3DResourcesCount } from '../Reveal3DResources/Reveal3DResourcesInfoContext'; import { isEqual } from 'lodash'; @@ -12,6 +12,7 @@ import { modelExists } from '../../utilities/modelExists'; import { getViewerResourceCount } from '../../utilities/getViewerResourceCount'; import { type CadModelStyling } from './types'; import { useApplyCadModelStyling } from './useApplyCadModelStyling'; +import { isSameGeometryFilter, isSameModel } from '../../utilities/isSameModel'; export type CogniteCadModelProps = { addModelOptions: AddModelOptions; @@ -32,6 +33,7 @@ export function CadModelContainer({ const viewer = useReveal(); const { setRevealResourcesCount } = useReveal3DResourcesCount(); const initializingModel = useRef(undefined); + const initializingModelsGeometryFilter = useRef(undefined); const [model, setModel] = useState(undefined); @@ -62,7 +64,12 @@ export function CadModelContainer({ useApplyCadModelStyling(model, styling); - useEffect(() => removeModel, [model]); + useEffect( + () => () => { + removeModel(model); + }, + [model] + ); return <>; @@ -82,18 +89,19 @@ export function CadModelContainer({ async function getOrAddModel(): Promise { const viewerModel = viewer.models.find( (model) => - model.modelId === modelId && - model.revisionId === revisionId && - model.getModelTransformation().equals(transform ?? new Matrix4()) + isSameModel(model, addModelOptions) && + isSameGeometryFilter(geometryFilter, initializingModelsGeometryFilter.current) ); + if (viewerModel !== undefined) { return await Promise.resolve(viewerModel as CogniteCadModel); } + initializingModelsGeometryFilter.current = geometryFilter; return await viewer.addCadModel(addModelOptions); } } - function removeModel(): void { + function removeModel(model: CogniteCadModel | undefined): void { if (!modelExists(model, viewer)) return; if (cachedViewerRef !== undefined && !cachedViewerRef.isRevealContainerMountedRef.current) @@ -101,7 +109,6 @@ export function CadModelContainer({ viewer.removeModel(model); setRevealResourcesCount(getViewerResourceCount(viewer)); - setModel(undefined); } } diff --git a/react-components/src/utilities/isSameModel.ts b/react-components/src/utilities/isSameModel.ts index b260d218141..895436ee665 100644 --- a/react-components/src/utilities/isSameModel.ts +++ b/react-components/src/utilities/isSameModel.ts @@ -22,7 +22,7 @@ export function isSameCadModel(model0: CadModelOptions, model1: CadModelOptions) ); } -function isSameGeometryFilter( +export function isSameGeometryFilter( filter0: GeometryFilter | undefined, filter1: GeometryFilter | undefined ): boolean { From 140eab7b7abe820dd7cd0f7b0edd1f92a396a73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= <70905152+haakonflatval-cognite@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:01:26 +0200 Subject: [PATCH 4/6] chore(react-components): bump to version 0.58.2 (#4755) --- react-components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-components/package.json b/react-components/package.json index 7ab156a1568..3f206b81052 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -1,6 +1,6 @@ { "name": "@cognite/reveal-react-components", - "version": "0.58.1", + "version": "0.58.2", "exports": { ".": { "import": "./dist/index.js", From e3575b0a01b54a85556dcb6f80a5fd4291604390 Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming <35219649+nilscognite@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:16:26 +0200 Subject: [PATCH 5/6] fix(react-components): Fix a small bug in compare equalsIgnoreCaseAndSpace and use correct undo icon --- .../src/architecture/base/concreteCommands/UndoCommand.ts | 2 +- .../architecture/base/utilities/extensions/stringExtensions.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/react-components/src/architecture/base/concreteCommands/UndoCommand.ts b/react-components/src/architecture/base/concreteCommands/UndoCommand.ts index 56eac50393c..99fff62133d 100644 --- a/react-components/src/architecture/base/concreteCommands/UndoCommand.ts +++ b/react-components/src/architecture/base/concreteCommands/UndoCommand.ts @@ -12,7 +12,7 @@ export class UndoCommand extends RenderTargetCommand { // ================================================== public override get icon(): string { - return 'Refresh'; // Should be 'Restore' but it doesn't exist + return 'Restore'; } public override get tooltip(): TranslateKey { diff --git a/react-components/src/architecture/base/utilities/extensions/stringExtensions.ts b/react-components/src/architecture/base/utilities/extensions/stringExtensions.ts index 9d5e398ed33..6015c6c2562 100644 --- a/react-components/src/architecture/base/utilities/extensions/stringExtensions.ts +++ b/react-components/src/architecture/base/utilities/extensions/stringExtensions.ts @@ -28,6 +28,7 @@ export function equalsIgnoreCaseAndSpace(value1: string, value2: string): boolea } const lowerChar2 = char2.toLowerCase(); if (lowerChar2 === lowerChar1) { + j++; break; } return false; From 59ff0d63ea2d4f0420405ce4b3c00b3b4db73b18 Mon Sep 17 00:00:00 2001 From: Pramod S <87521752+pramodcog@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:56:46 +0530 Subject: [PATCH 6/6] fix(react-components): resources count when unreferenced model is removed (#4757) * fixed resources count update when unreferenced model is removed * bump react-component version to 0.58.3 * fixed test failing --- react-components/package.json | 2 +- .../useRemoveNonReferencedModels.ts | 4 ++ ... => useRemoveNonReferencedModels.test.tsx} | 43 ++++++++++++++----- .../hooks/useCameraStateControl.test.ts | 33 ++++++++------ .../tests/unit-tests/fixtures/cadModel.ts | 2 +- .../tests/unit-tests/fixtures/viewer.ts | 15 +++---- 6 files changed, 63 insertions(+), 36 deletions(-) rename react-components/tests/unit-tests/components/Reveal3DResources/{useRemoveNonReferencedModels.test.ts => useRemoveNonReferencedModels.test.tsx} (59%) diff --git a/react-components/package.json b/react-components/package.json index 3f206b81052..b91ca27373b 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -1,6 +1,6 @@ { "name": "@cognite/reveal-react-components", - "version": "0.58.2", + "version": "0.58.3", "exports": { ".": { "import": "./dist/index.js", diff --git a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts index 414b8d55ae1..403329d39bb 100644 --- a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts +++ b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts @@ -10,11 +10,14 @@ import { } from './typeGuards'; import { useEffect } from 'react'; import { isSameModel } from '../../utilities/isSameModel'; +import { useReveal3DResourcesCount } from './Reveal3DResourcesInfoContext'; +import { getViewerResourceCount } from '../../utilities/getViewerResourceCount'; export function useRemoveNonReferencedModels( addOptions: AddResourceOptions[], viewer: Cognite3DViewer ): void { + const { setRevealResourcesCount } = useReveal3DResourcesCount(); useEffect(() => { const nonReferencedModels = findNonReferencedModels(addOptions, viewer); @@ -27,6 +30,7 @@ export function useRemoveNonReferencedModels( nonReferencedCollections.forEach((collection) => { viewer.remove360ImageSet(collection); }); + setRevealResourcesCount(getViewerResourceCount(viewer)); }, [addOptions]); } diff --git a/react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.ts b/react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.tsx similarity index 59% rename from react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.ts rename to react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.tsx index d2af83fdd7c..6f44ac5ab2d 100644 --- a/react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.ts +++ b/react-components/tests/unit-tests/components/Reveal3DResources/useRemoveNonReferencedModels.test.tsx @@ -1,6 +1,5 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; - -import { Mock } from 'moq.ts'; +import React, { type JSX } from 'react'; import { renderHook } from '@testing-library/react'; @@ -12,36 +11,54 @@ import { viewerModelsMock, viewerRemoveModelsMock } from '../../fixtures/viewer'; +import { Reveal3DResourcesInfoContextProvider } from '../../../../src/components/Reveal3DResources/Reveal3DResourcesInfoContext'; import { cadMock, cadModelOptions } from '../../fixtures/cadModel'; import { pointCloudMock, pointCloudModelOptions } from '../../fixtures/pointCloud'; import { image360Mock, image360Options } from '../../fixtures/image360'; +import { EMPTY_ARRAY } from '../../../../src/utilities/constants'; describe(useRemoveNonReferencedModels.name, () => { beforeEach(() => { vi.resetAllMocks(); }); + const wrapper = ({ children }: { children: React.ReactNode }): JSX.Element => ( + {children} + ); test('does not crash when no models are added', () => { viewerModelsMock.mockReturnValue([]); viewerImage360CollectionsMock.mockReturnValue([]); - expect(() => renderHook(() => useRemoveNonReferencedModels([], viewerMock))).not.toThrow(); + expect(() => + renderHook( + () => { + useRemoveNonReferencedModels(EMPTY_ARRAY, viewerMock); + }, + { wrapper } + ) + ).not.toThrow(); }); test('removes models when empty ', () => { viewerModelsMock.mockReturnValue([cadMock]); viewerImage360CollectionsMock.mockReturnValue([]); - renderHook(() => useRemoveNonReferencedModels([], viewerMock)); + renderHook( + () => { + useRemoveNonReferencedModels(EMPTY_ARRAY, viewerMock); + }, + { wrapper } + ); expect(viewerRemoveModelsMock).toHaveBeenCalledOnce(); }); test('does not remove models when in addOptions', () => { viewerModelsMock.mockReturnValue([pointCloudMock, cadMock]); viewerImage360CollectionsMock.mockReturnValue([image360Mock]); - renderHook(() => - useRemoveNonReferencedModels( - [cadModelOptions, pointCloudModelOptions, image360Options], - viewerMock - ) + const mockAddOptions = [pointCloudModelOptions, cadModelOptions, image360Options]; + renderHook( + () => { + useRemoveNonReferencedModels(mockAddOptions, viewerMock); + }, + { wrapper } ); expect(viewerRemoveModelsMock).not.toHaveBeenCalled(); }); @@ -49,7 +66,13 @@ describe(useRemoveNonReferencedModels.name, () => { test('removes only relevant model', () => { viewerModelsMock.mockReturnValue([pointCloudMock, cadMock]); viewerImage360CollectionsMock.mockReturnValue([image360Mock]); - renderHook(() => useRemoveNonReferencedModels([cadModelOptions, image360Options], viewerMock)); + const mockAddOptions = [cadModelOptions, image360Options]; + renderHook( + () => { + useRemoveNonReferencedModels(mockAddOptions, viewerMock); + }, + { wrapper } + ); expect(viewerRemoveModelsMock).toHaveBeenCalledWith(pointCloudMock); }); }); diff --git a/react-components/tests/unit-tests/components/RevealCanvas/hooks/useCameraStateControl.test.ts b/react-components/tests/unit-tests/components/RevealCanvas/hooks/useCameraStateControl.test.ts index 00f1819d587..62f3faaaf50 100644 --- a/react-components/tests/unit-tests/components/RevealCanvas/hooks/useCameraStateControl.test.ts +++ b/react-components/tests/unit-tests/components/RevealCanvas/hooks/useCameraStateControl.test.ts @@ -4,7 +4,7 @@ import { renderHook } from '@testing-library/react'; import { viewerMock } from '../../../fixtures/viewer'; import { - CameraStateParameters, + type CameraStateParameters, useCameraStateControl } from '../../../../../src/components/RevealCanvas/hooks/useCameraStateControl'; import { Vector3 } from 'three'; @@ -28,20 +28,24 @@ describe(useCameraStateControl.name, () => { }); test('does nothing when inputs are undefined', () => { - const { rerender } = renderHook(() => useCameraStateControl()); + const { rerender } = renderHook(() => { + useCameraStateControl(); + }); vi.runAllTimers(); rerender(); vi.runAllTimers(); - cameraManagerGlobalCameraEvents.cameraStop.forEach((mockCallback) => - expect(mockCallback).not.toBeCalled() - ); + cameraManagerGlobalCameraEvents.cameraStop.forEach((mockCallback) => { + expect(mockCallback).not.toBeCalled(); + }); }); test('does nothing if external camera state is undefined', () => { const setter = vi.fn(); - const { rerender } = renderHook(() => useCameraStateControl(undefined, setter)); + const { rerender } = renderHook(() => { + useCameraStateControl(undefined, setter); + }); vi.runAllTimers(); rerender(); @@ -54,8 +58,9 @@ describe(useCameraStateControl.name, () => { const setter = vi.fn<[CameraStateParameters | undefined], void>(); const { rerender } = renderHook( - ({ position }: { position: Vector3 }) => - useCameraStateControl({ position: position.clone(), target: new Vector3(1, 1, 1) }, setter), + ({ position }: { position: Vector3 }) => { + useCameraStateControl({ position: position.clone(), target: new Vector3(1, 1, 1) }, setter); + }, { initialProps: { position: new Vector3(0, 0, 0) } } ); @@ -65,20 +70,20 @@ describe(useCameraStateControl.name, () => { vi.runAllTimers(); expect(setter).not.toBeCalled(); - cameraManagerGlobalCameraEvents.cameraStop.forEach((mockCallback) => - expect(mockCallback).toBeCalledTimes(1) - ); + cameraManagerGlobalCameraEvents.cameraStop.forEach((mockCallback) => { + expect(mockCallback).toBeCalledTimes(1); + }); }); test('provided setter is called after updating camera state internally', () => { const setter = vi.fn<[CameraStateParameters | undefined], void>(); - const { rerender } = renderHook(() => + const { rerender } = renderHook(() => { useCameraStateControl( { position: new Vector3(0, 0, 0), target: new Vector3(1, 1, 1) }, setter - ) - ); + ); + }); vi.runAllTimers(); diff --git a/react-components/tests/unit-tests/fixtures/cadModel.ts b/react-components/tests/unit-tests/fixtures/cadModel.ts index 6d9c3559164..2227193b1b6 100644 --- a/react-components/tests/unit-tests/fixtures/cadModel.ts +++ b/react-components/tests/unit-tests/fixtures/cadModel.ts @@ -1,4 +1,4 @@ -import { CogniteCadModel } from '@cognite/reveal'; +import { type CogniteCadModel } from '@cognite/reveal'; import { Mock } from 'moq.ts'; import { Matrix4 } from 'three'; diff --git a/react-components/tests/unit-tests/fixtures/viewer.ts b/react-components/tests/unit-tests/fixtures/viewer.ts index 5c9f797f883..be8822cbd30 100644 --- a/react-components/tests/unit-tests/fixtures/viewer.ts +++ b/react-components/tests/unit-tests/fixtures/viewer.ts @@ -1,14 +1,7 @@ -import { vi, Mock as viMock } from 'vitest'; +import { vi } from 'vitest'; -import { - CameraManagerEventType, - Cognite3DViewer, - CogniteModel, - Image360Collection -} from '@cognite/reveal'; +import { type Cognite3DViewer, type CogniteModel, type Image360Collection } from '@cognite/reveal'; import { Mock, It } from 'moq.ts'; -import { Vector3 } from 'three'; -import { remove } from 'lodash'; import { cameraManagerMock } from './cameraManager'; const domElement = document.createElement('div').appendChild(document.createElement('canvas')); @@ -18,7 +11,9 @@ export const viewerRemoveModelsMock = vi.fn<[CogniteModel], void>(); export const viewerImage360CollectionsMock = vi.fn<[], Image360Collection[]>(); export const viewerMock = new Mock() - .setup((viewer) => viewer.setBackgroundColor(It.IsAny())) + .setup((viewer) => { + viewer.setBackgroundColor(It.IsAny()); + }) .returns() .setup((viewer) => viewer.domElement) .returns(domElement)