Skip to content

Commit

Permalink
feat(react-components): add Reveal container and container for Cognit…
Browse files Browse the repository at this point in the history
…eCadModel (#3419)

* chore: restructure folder layout

* asd

* asd

* feat: add RevealContainer

* fix: update transformation when updating prop

* fix: conflicts

* fix: update storybook setup

* fix: update reveal version

* fix: QA

---------

Co-authored-by: cognite-bulldozer[bot] <51074376+cognite-bulldozer[bot]@users.noreply.github.com>
  • Loading branch information
christjt and cognite-bulldozer[bot] authored Jun 26, 2023
1 parent e6130fa commit f8581af
Show file tree
Hide file tree
Showing 17 changed files with 309 additions and 187 deletions.
8 changes: 5 additions & 3 deletions react-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
"@babel/preset-env": "7.22.5",
"@babel/preset-react": "7.22.5",
"@babel/preset-typescript": "7.22.5",
"@cognite/cogs.js": "^9.13.2",
"@cognite/reveal": "^4.3.1",
"@cognite/cogs.js": "^9.17.0",
"@cognite/reveal": "4.3.4",
"@cognite/sdk": "^8.2.0",
"@storybook/addon-essentials": "7.0.23",
"@storybook/addon-interactions": "7.0.23",
"@storybook/addon-links": "7.0.23",
Expand All @@ -35,7 +36,7 @@
"@storybook/react-webpack5": "7.0.23",
"@storybook/testing-library": "0.2.0",
"@types/lodash": "^4.14.190",
"@types/react": "18.2.12",
"@types/react": "18.2.7",
"@types/styled-components": "5.1.26",
"@types/three": "0.152.0",
"moq.ts": "^10.0.6",
Expand All @@ -44,6 +45,7 @@
"react-dom": "18.2.0",
"storybook": "7.0.23",
"styled-components": "5.3.11",
"three": "0.152.2",
"ts-loader": "9.4.3",
"typescript": "5.1.3",
"webpack": "5.87.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useEffect, useRef } from "react";
import { AddModelOptions, CogniteCadModel } from "@cognite/reveal";
import { useReveal } from "../RevealContainer/RevealContext";
import { Matrix4 } from "three";

type Cognite3dModelProps = {
addModelOptions: AddModelOptions;
transform?: THREE.Matrix4;
};

export default function CogniteCadModelContainer({
addModelOptions,
transform,
}: Cognite3dModelProps) {
const modelRef = useRef<CogniteCadModel>();
const viewer = useReveal();
const { modelId, revisionId } = addModelOptions;

useEffect(() => {
addModel(modelId, revisionId, transform).catch(console.error);
return () => {
if (
modelRef.current === undefined ||
!viewer.models.includes(modelRef.current)
) {
return;
}
viewer.removeModel(modelRef.current);
modelRef.current = undefined;
};
}, [addModelOptions]);

useEffect(() => {
if (modelRef.current === undefined || transform === undefined) return;
modelRef.current.setModelTransformation(transform);
}, [transform]);

return <></>;

async function addModel(
modelId: number,
revisionId: number,
transform?: Matrix4
) {
const cadModel = await viewer.addCadModel({ modelId, revisionId });
if (transform !== undefined) {
cadModel.setModelTransformation(transform);
}
modelRef.current = cadModel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

import { Cognite3DViewer, Image360 } from '@cognite/reveal';
import React, { useEffect, useRef, useState } from 'react';
import { Image360HistoricalPanel } from '../Panel/Image360HistoricalPanel';
import { Image360HistoricalSummary } from '../Toolbar/Image360HistoricalSummary';
import { formatDate } from '../utils/FormatDate';
import { Image360HistoricalPanel } from './Panel/Image360HistoricalPanel';
import { Image360HistoricalSummary } from './Toolbar/Image360HistoricalSummary';
import { formatDate } from './utils/FormatDate';
import styled from 'styled-components';
// Using named import to avoid react component creation error when default import is used.
import { uniqueId } from 'lodash';
import uniqueId from 'lodash/uniqueId';

export interface Image360HistoricalDetailsProps {
viewer: Cognite3DViewer;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CogniteClient } from "@cognite/sdk";
import { useEffect, useRef, ReactNode, useState, useMemo } from "react";
import { Cognite3DViewer } from '@cognite/reveal';
import { RevealContext } from "./RevealContext";
import { Color } from "three";

type RevealContainerProps = {
color?: Color;
sdk: CogniteClient;
children?: ReactNode;
}

export default function RevealContainer({ children, sdk, color }: RevealContainerProps) {
const [viewer, setViewer] = useState<Cognite3DViewer>();
const revealDomElementRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const viewer = new Cognite3DViewer({ sdk, domElement: revealDomElementRef.current! });
viewer.setBackgroundColor({ color, alpha: 1 })
setViewer(viewer);
return () => {
viewer.dispose();
setViewer(undefined);
}
}, []);

const mountChildren = (viewer: Cognite3DViewer | undefined) => {
if (viewer === undefined) return <></>;
return (
<>
<RevealContext.Provider value={viewer}>
{children}
</RevealContext.Provider>
</>
)
}

return (
<div ref={revealDomElementRef}>
{mountChildren(viewer)}
</div>
);
}
12 changes: 12 additions & 0 deletions react-components/src/components/RevealContainer/RevealContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Cognite3DViewer } from '@cognite/reveal';
import {createContext, useContext} from 'react';

export const RevealContext = createContext<Cognite3DViewer | null>(null);

export const useReveal = () => {
const reveal = useContext(RevealContext);
if (!reveal) {
throw new Error('useReveal must be used within a RevealProvider');
}
return reveal;
}
1 change: 0 additions & 1 deletion react-components/src/components/View/index.ts

This file was deleted.

4 changes: 3 additions & 1 deletion react-components/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
import '@cognite/cogs.js/dist/cogs.css';
export { Image360HistoricalDetails } from './View';
export { default as RevealContainer } from './RevealContainer/RevealContainer';
export { default as CogniteCadModelContainer } from './CogniteCadModelContainer/CogniteCadModelContainer';
export { Image360HistoricalDetails } from './Image360HistoricalDetails/Image360HistoricalDetails';
41 changes: 41 additions & 0 deletions react-components/src/stories/CogniteCadModelContainer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Meta, StoryObj } from "@storybook/react";
import { CogniteCadModelContainer, RevealContainer } from "..";
import { CogniteClient } from "@cognite/sdk";
import { Color, Matrix4 } from "three";

const meta = {
title: "Example/CogniteCadModelContainer",
component: CogniteCadModelContainer,
tags: ["autodocs"],
} satisfies Meta<typeof CogniteCadModelContainer>;

export default meta;
type Story = StoryObj<typeof meta>;

// TODO: See if we can improve this with some proper authentication
const token = new URLSearchParams(window.location.search).get("token")!;
const sdk = new CogniteClient({
appId: "reveal.example",
baseUrl: "https://greenfield.cognitedata.com",
project: "3d-test",
getToken: () => Promise.resolve(token),
});

export const Main: Story = {
args: {
addModelOptions: {
modelId: 1791160622840317,
revisionId: 498427137020189,
},
transform: new Matrix4().makeTranslation(0, 10, 0),
},
render: ({ addModelOptions, transform }) => (
<RevealContainer sdk={sdk} color={new Color(0x4a4a4a)}>
<CogniteCadModelContainer addModelOptions={addModelOptions} />
<CogniteCadModelContainer
addModelOptions={addModelOptions}
transform={transform}
/>
</RevealContainer>
),
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Image360HistoricalDetails } from '../components/View';
import { Image360HistoricalDetails } from '..';
import { It, Mock } from 'moq.ts';
import { Cognite3DViewer, Image360, Image360Revision } from '@cognite/reveal';

Expand Down
5 changes: 2 additions & 3 deletions react-components/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
{
"compilerOptions": {
"target": "ES6",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"skipLibCheck": false,
"jsx": "react-jsx",
"module": "ESNext",
"declaration": true,
Expand All @@ -21,4 +20,4 @@
"exclude": [
"**/*.stories.ts"
]
}
}
Loading

0 comments on commit f8581af

Please sign in to comment.