Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 3D Resources layering react component #3495

Merged
merged 32 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
792cd83
Initial layering component for Cad model
pramodcog Jul 13, 2023
0616cb8
Added sliders and adjusted UI for submenu
pramodcog Jul 18, 2023
c088b5c
Fixed lint error
pramodcog Jul 18, 2023
4678f7a
fixed 360 image visibility issue
pramodcog Jul 19, 2023
dfb89a4
Improved UI when one of the 3D resources is not available
pramodcog Jul 19, 2023
4131913
removed opacity from 3D resources layers option
pramodcog Jul 19, 2023
1265edd
removed additional elements which was not needed
pramodcog Jul 19, 2023
0b8d378
Merge branch 'master' into pramodcog/UX-958
pramodcog Jul 19, 2023
730f9c2
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
9be5903
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
3bc6a7a
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
63740d5
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
7ea401c
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
b7e4e83
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
31d2ec4
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
162de70
added indeterminate option for checkbox and exposed LayerButton
pramodcog Jul 20, 2023
ed0e47b
Merge branch 'pramodcog/UX-958' of https://github.com/cognitedata/rev…
pramodcog Jul 20, 2023
8803ace
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 20, 2023
84253c9
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 20, 2023
9ca0c2f
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 20, 2023
b4b0b6d
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 20, 2023
3e04bec
Added model name & number of models in each 3D resources UI
pramodcog Jul 21, 2023
8eec958
updated component key to lodash/uniqueId
pramodcog Jul 21, 2023
892d250
Merge branch 'master' into pramodcog/UX-958
pramodcog Jul 21, 2023
6f7e5ab
Merge refs/heads/master into pramodcog/UX-958
cognite-bulldozer[bot] Jul 24, 2023
c0c608c
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 24, 2023
3adb0b5
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 24, 2023
a79d324
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 24, 2023
a953a95
Update react-components/src/components/RevealToolbar/LayersContainer/…
pramodcog Jul 24, 2023
3a34e4c
Update react-components/src/hooks/use3DModelName.tsx
pramodcog Jul 24, 2023
fcc1c80
addresed review comments
pramodcog Jul 24, 2023
759ee6f
Updated pointCloud & 360 image count number styling
pramodcog Jul 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions react-components/src/components/RevealToolbar/LayersButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*!
* Copyright 2023 Cognite AS
*/

import { type ReactElement, useState } from 'react';
import { Button, Dropdown } from '@cognite/cogs.js';
import { LayersContainer } from './LayersContainer/LayersContainer';

export const LayersButton = (): ReactElement => {
const [layersEnabled, setLayersEnabled] = useState(false);
const showLayers = (): void => {
setLayersEnabled(!layersEnabled);
};

return (
<Dropdown
appendTo={document.body}
content={<LayersContainer />}
visible={layersEnabled}
placement="auto">
<Button type="ghost" icon="Layers" aria-label="3D Resource layers" onClick={showLayers} />
</Dropdown>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* Copyright 2023 Cognite AS
*/

import React, { type ReactElement, useState } from 'react';
import { useReveal } from '../../RevealContainer/RevealContext';
import { type CogniteCadModel } from '@cognite/reveal';
import { Menu } from '@cognite/cogs.js';
import { StyledCheckbox, StyledSubMenu, StyledMenu } from './elements';

export const CadModelLayersContainer = (): ReactElement => {
const viewer = useReveal();
const cadModels = viewer.models.filter((model) => model.type === 'cad');

const [selectedCadModels, setSelectedCadModels] = useState<
Array<{ model: CogniteCadModel; isToggled: boolean }>
>(
cadModels.map((model) => ({
model: model as CogniteCadModel,
isToggled: (model as CogniteCadModel).visible
}))
);

const [allCadModelVisible, setAllCadModelVisible] = useState(true);
const [indeterminate, setIndeterminate] = useState<boolean>(false);

const handleCadModelVisibility = (model: CogniteCadModel): void => {
selectedCadModels.map((data) => {
if (data.model === model) {
data.isToggled = !data.isToggled;
}
return data;
});
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
model.visible = !model.visible;
viewer.requestRedraw();
setSelectedCadModels([...selectedCadModels]);
setIndeterminate(selectedCadModels.some((data) => !data.isToggled));
setAllCadModelVisible(!selectedCadModels.every((data) => !data.isToggled));
};

const handleAllCadModelsVisibility = (visible: boolean): void => {
selectedCadModels.forEach((data) => {
data.isToggled = visible;
data.model.visible = visible;
});
viewer.requestRedraw();
setAllCadModelVisible(visible);
setIndeterminate(false);
setSelectedCadModels([...selectedCadModels]);
};

const cadModelContent = (): React.JSX.Element => {
return (
<StyledSubMenu>
{selectedCadModels.map((data) => (
<Menu.Item
key={data.model.modelId}
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
hasCheckbox
checkboxProps={{
checked: data.isToggled,
onChange: (e: { stopPropagation: () => void }) => {
e.stopPropagation();
handleCadModelVisibility(data.model);
}
}}>
{data.model.modelId}
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
</Menu.Item>
))}
</StyledSubMenu>
);
};

return (
<>
{selectedCadModels.length > 0 ? (
<StyledMenu>
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
<StyledCheckbox
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
checked={allCadModelVisible}
indeterminate={indeterminate}
onChange={(e, c) => {
e.stopPropagation();
handleAllCadModelsVisibility(c as boolean);
}}
/>
<Menu.Submenu content={cadModelContent()}>CAD models</Menu.Submenu>
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
</StyledMenu>
) : (
<></>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* Copyright 2023 Cognite AS
*/

import React, { type ReactElement, useState } from 'react';
import { useReveal } from '../../RevealContainer/RevealContext';
import { Menu } from '@cognite/cogs.js';
import { StyledCheckbox, StyledSubMenu, StyledMenu } from './elements';
import { type Image360Collection } from '@cognite/reveal';

export const Image360CollectionLayerContainer = (): ReactElement => {
const viewer = useReveal();
const image360Collection = viewer.get360ImageCollections();

const [selectedImage360Collection, setSelectedImage360Collection] = useState<
Array<{ image360: Image360Collection; isToggled: boolean }>
>(
image360Collection.map((image360Collection) => ({
image360: image360Collection,
isToggled: true
}))
);

const [all360ImagesVisible, setAll360ImagesVisible] = useState(true);
const [indeterminate, setIndeterminate] = useState<boolean>(false);

const handle360ImagesVisibility = (image360: Image360Collection): void => {
selectedImage360Collection.map((data) => {
if (data.image360 === image360) {
data.isToggled = !data.isToggled;
image360.setIconsVisibility(data.isToggled);
}
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
return data;
});
viewer.requestRedraw();
setSelectedImage360Collection([...selectedImage360Collection]);
setIndeterminate(selectedImage360Collection.some((data) => !data.isToggled));
setAll360ImagesVisible(!selectedImage360Collection.every((data) => !data.isToggled));
};

const handleAll360ImagesVisibility = (visible: boolean): void => {
selectedImage360Collection.forEach((data) => {
data.isToggled = visible;
data.image360.setIconsVisibility(data.isToggled);
});
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
viewer.requestRedraw();
setAll360ImagesVisible(visible);
setIndeterminate(false);
setSelectedImage360Collection([...selectedImage360Collection]);
};

const image360Content = (): React.JSX.Element => {
return (
<StyledSubMenu>
{selectedImage360Collection.map((data) => (
<Menu.Item
key={data.image360.id}
hasCheckbox
checkboxProps={{
checked: data.isToggled,
onChange: (e: { stopPropagation: () => void }) => {
e.stopPropagation();
handle360ImagesVisibility(data.image360);
}
}}>
{data.image360.label}
</Menu.Item>
))}
</StyledSubMenu>
);
};

return (
<>
{selectedImage360Collection.length > 0 ? (
<StyledMenu>
<StyledCheckbox
checked={all360ImagesVisible}
indeterminate={indeterminate}
onChange={(e, c) => {
e.stopPropagation();
handleAll360ImagesVisibility(c as boolean);
}}
/>
<Menu.Submenu content={image360Content()}>360 images</Menu.Submenu>
</StyledMenu>
) : (
<></>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*!
* Copyright 2023 Cognite AS
*/

import { type ReactElement } from 'react';

import { Menu } from '@cognite/cogs.js';
import styled from 'styled-components';

import { CadModelLayersContainer } from './CadModelLayersContainer';
import { PointCloudLayersContainer } from './PointCloudLayersContainer';
import { Image360CollectionLayerContainer } from './Image360LayersContainer';

export const LayersContainer = (): ReactElement => {
return (
<Container>
<StyleMenu>
<CadModelLayersContainer />
<PointCloudLayersContainer />
<Image360CollectionLayerContainer />
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
</StyleMenu>
</Container>
);
};

const Container = styled.div`
position: absolute;
left: calc(0%);
top: calc(-70%);
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
`;

const StyleMenu = styled(Menu)`
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
display: flex;
flex-direction: column;
padding: 0px 0px 0px 0px;
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* Copyright 2023 Cognite AS
*/

import React, { type ReactElement, useState } from 'react';

import { useReveal } from '../../RevealContainer/RevealContext';
import { Menu } from '@cognite/cogs.js';
import { StyledCheckbox, StyledSubMenu, StyledMenu } from './elements';
import { type CognitePointCloudModel } from '@cognite/reveal';

export const PointCloudLayersContainer = (): ReactElement => {
const viewer = useReveal();
const pointCloudModels = viewer.models.filter((model) => model.type === 'pointcloud');

const [selectedPointCloudModels, setSelectedPointCloudModels] = useState<
Array<{ model: CognitePointCloudModel; isToggled: boolean }>
>(
pointCloudModels.map((model) => ({
model: model as CognitePointCloudModel,
isToggled: (model as CognitePointCloudModel).getDefaultPointCloudAppearance().visible ?? true
}))
);

const [allPointCloudModelVisible, setAllPointCloudModelVisible] = useState(true);
const [indeterminate, setIndeterminate] = useState<boolean>(false);

const handlePointCloudVisibility = (model: CognitePointCloudModel): void => {
selectedPointCloudModels.map((data) => {
if (data.model === model) {
data.isToggled = !data.isToggled;
model.setDefaultPointCloudAppearance({ visible: data.isToggled });
}
return data;
});
viewer.requestRedraw();
setSelectedPointCloudModels([...selectedPointCloudModels]);
setIndeterminate(selectedPointCloudModels.some((data) => !data.isToggled));
setAllPointCloudModelVisible(!selectedPointCloudModels.every((data) => !data.isToggled));
};

const handleAllPointCloudModelsVisibility = (visible: boolean): void => {
selectedPointCloudModels.forEach((data) => {
data.isToggled = visible;
data.model.setDefaultPointCloudAppearance({ visible });
});
viewer.requestRedraw();
setAllPointCloudModelVisible(visible);
setSelectedPointCloudModels([...selectedPointCloudModels]);
};

const pointCloudModelContent = (): React.JSX.Element => {
return (
<StyledSubMenu>
{selectedPointCloudModels.map((data) => (
<Menu.Item
key={data.model.modelId}
hasCheckbox
checkboxProps={{
checked: data.isToggled,
onChange: (e: { stopPropagation: () => void }) => {
e.stopPropagation();
handlePointCloudVisibility(data.model);
}
}}>
{data.model.modelId}
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
</Menu.Item>
))}
</StyledSubMenu>
);
};

return (
<>
{selectedPointCloudModels.length > 0 ? (
<StyledMenu>
<StyledCheckbox
checked={allPointCloudModelVisible}
indeterminate={indeterminate}
onChange={(e, c) => {
e.stopPropagation();
handleAllPointCloudModelsVisibility(c as boolean);
}}
/>
<Menu.Submenu content={pointCloudModelContent()}>Point clouds</Menu.Submenu>
</StyledMenu>
) : (
<></>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*!
* Copyright 2023 Cognite AS
*/

import { Checkbox, Menu } from '@cognite/cogs.js';
import styled from 'styled-components';

export const StyledCheckbox = styled(Checkbox)`
margin-left: 10px;
`;

export const StyledMenu = styled(Menu)`
display: flex;
flex-direction: row;
box-shadow: none;
padding: 0px;
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
`;

export const StyledSubMenu = styled(Menu)`
box-shadow: none;
padding: 8px;
`;
pramodcog marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { type ReactElement } from 'react';
import { Button, ToolBar, type ToolBarProps } from '@cognite/cogs.js';
import { FitModelsButton } from './FitModelsButton';
import { LayersButton } from './LayersButton';

const defaultStyle: ToolBarProps = {
style: {
Expand All @@ -21,7 +22,7 @@ export const RevealToolbar = (toolBarProps: ToolBarProps): ReactElement => {
return (
<ToolBar {...toolBarProps}>
<>
<Button type="ghost" icon="Layers" aria-label="3D Resource layers" />
<LayersButton />

<div className="cogs-toolbar-divider" />

Expand Down
1 change: 1 addition & 0 deletions react-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ export type {
AddReveal3DModelOptions
} from './components/Reveal3DResources/types';
export { RevealToolbar } from './components/RevealToolbar/RevealToolbar';
export { LayersButton } from './components/RevealToolbar/LayersButton';
export { useFdmAssetMappings } from './hooks/useFdmAssetMappings';
export { type FdmAssetMappingsConfig } from './hooks/types';
Loading
Loading