Skip to content

Commit

Permalink
fix(composer): error handling for Matterport scene
Browse files Browse the repository at this point in the history
  • Loading branch information
mukeshsahay committed May 19, 2023
1 parent aaf6338 commit 24ca493
Show file tree
Hide file tree
Showing 21 changed files with 46,933 additions and 61,507 deletions.
108,081 changes: 46,651 additions & 61,430 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/scene-composer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"convert-svg": "npx @svgr/cli --out-dir src/assets/auto-gen/icons/ --typescript --index-template tools/index-template.js -- src/assets/icons/",
"release": "run-s compile copy-assets",
"copy-assets": "copyfiles -e \"**/*.tsx\" -e \"**/*.ts\" -e \"**/*.snap\" -e \"**/*.js\" -e \"**/*.jsx\" -e \"**/*.json\" \"src/**/*\" dist/",
"lint": "eslint . --max-warnings=735",
"lint": "eslint . --max-warnings=718",
"fix": "eslint --fix .",
"test": "jest --config jest.config.ts --coverage --silent",
"test:dev": "jest --config jest.config.ts --coverage",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('AnchorWidget', () => {
componentVisibilities: { [KnownComponentType.Tag]: tagVisible },
toggleComponentVisibility: jest.fn(),
setTagSettings: jest.fn(),
setMatterportViewerEnabled: jest.fn(),
setConnectionNameForMatterportViewer: jest.fn(),
},
});
};
Expand Down
1 change: 1 addition & 0 deletions packages/scene-composer/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,4 @@ export const SECRET_MANAGER_MATTERPORT_TAG = 'AWSIoTTwinMaker_Matterport';
export const MATTERPORT_SECRET_ARN = 'MATTERPORT_SECRET_ARN';
export const MATTERPORT_ACCESS_TOKEN = 'MATTERPORT_ACCESS_TOKEN';
export const MATTERPORT_APPLICATION_KEY = 'MATTERPORT_APPLICATION_KEY';
export const MATTERPORT_ERROR = 'MATTERPORT_ERROR';
32 changes: 24 additions & 8 deletions packages/scene-composer/src/components/StateManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ import {
setMetricRecorder,
setTwinMakerSceneMetadataModule,
} from '../common/GlobalSettings';
import { MATTERPORT_ACCESS_TOKEN, MATTERPORT_APPLICATION_KEY, MATTERPORT_SECRET_ARN } from '../common/constants';
import {
MATTERPORT_ACCESS_TOKEN,
MATTERPORT_APPLICATION_KEY,
MATTERPORT_ERROR,
MATTERPORT_SECRET_ARN,
} from '../common/constants';
import { DisplayMessageCategory } from '../store/internalInterfaces';
import { useSceneComposerId } from '../common/sceneComposerIdContext';
import useActiveCamera from '../hooks/useActiveCamera';
import useMatterportViewer from '../hooks/useMatterportViewer';
import {
AdditionalComponentData,
ExternalLibraryConfig,
Expand Down Expand Up @@ -73,6 +80,7 @@ const StateManager: React.FC<SceneComposerInternalProps> = ({
setSelectedSceneNodeRef,
getSceneNodeByRef,
getObject3DBySceneNodeRef,
addMessages,
} = useStore(sceneComposerId)((state) => state);
const [sceneContentUri, setSceneContentUri] = useState<string>('');
const [sceneContent, setSceneContent] = useState<string>('');
Expand All @@ -86,7 +94,9 @@ const StateManager: React.FC<SceneComposerInternalProps> = ({
const matterportModelId = useStore(sceneComposerId)((state) =>
state.getSceneProperty(KnownSceneProperty.MatterportModelId),
);
const { enableMatterportViewer, setMatterportViewerEnabled } = useViewOptionState(sceneComposerId);
const { connectionNameForMatterportViewer, setConnectionNameForMatterportViewer } =
useViewOptionState(sceneComposerId);
const { enableMatterportViewer } = useMatterportViewer();

const dataProviderRef = useRef<ProviderWithViewport<TimeSeriesData[]> | undefined>(undefined);
const prevSelection = useRef<string | undefined>(undefined);
Expand Down Expand Up @@ -120,14 +130,12 @@ const StateManager: React.FC<SceneComposerInternalProps> = ({
onSelectionChanged,
]);

// Initialize enableMatterportViewer on scene loading
// Initialize ConnectionNameForMatterportViewer on scene loading
useEffect(() => {
if (sceneMetadataModule) {
sceneMetadataModule.getSceneInfo().then((getSceneResponse) => {
if (getSceneResponse && getSceneResponse.sceneMetadata) {
const matterportViewerEnabled =
matterportModelId && getSceneResponse.sceneMetadata[MATTERPORT_SECRET_ARN] !== undefined;
setMatterportViewerEnabled(matterportViewerEnabled);
setConnectionNameForMatterportViewer(getSceneResponse.sceneMetadata[MATTERPORT_SECRET_ARN]);
}
});
}
Expand Down Expand Up @@ -270,7 +278,9 @@ const StateManager: React.FC<SceneComposerInternalProps> = ({
sceneMetadataModule
.getSceneInfo()
.then((sceneInfo) => {
if (sceneInfo && sceneInfo.generatedSceneMetadata) {
if (sceneInfo.error && sceneInfo.error.code === MATTERPORT_ERROR && sceneInfo.error.message) {
addMessages([{ category: DisplayMessageCategory.Warning, messageText: sceneInfo.error.message }]);
} else if (sceneInfo && sceneInfo.generatedSceneMetadata) {
const accessToken = sceneInfo.generatedSceneMetadata[MATTERPORT_ACCESS_TOKEN];
const applicationKey = sceneInfo.generatedSceneMetadata[MATTERPORT_APPLICATION_KEY];

Expand All @@ -291,7 +301,13 @@ const StateManager: React.FC<SceneComposerInternalProps> = ({
} else {
setUpdatedExternalLibraryConfig({ ...externalLibraryConfig });
}
}, [enableMatterportViewer, externalLibraryConfig, sceneMetadataModule]);
}, [
enableMatterportViewer,
connectionNameForMatterportViewer,
matterportModelId,
externalLibraryConfig,
sceneMetadataModule,
]);

// load scene content
useLayoutEffect(() => {
Expand Down
5 changes: 3 additions & 2 deletions packages/scene-composer/src/components/WebGLCanvasManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ThreeEvent, useThree } from '@react-three/fiber';

import { KnownSceneProperty } from '../interfaces';
import useLifecycleLogging from '../logger/react-logger/hooks/useLifecycleLogging';
import { useEditorState, useSceneDocument, useStore, useViewOptionState } from '../store';
import { useEditorState, useSceneDocument, useStore } from '../store';
import { sceneComposerIdContext } from '../common/sceneComposerIdContext';
import { hexColorFromDesignToken } from '../utils/styleUtils';
import { Layers, ROOT_OBJECT_3D_NAME } from '../common/constants';
Expand All @@ -15,6 +15,7 @@ import { ViewCursorWidget } from '../augmentations/components/three-fiber/viewpo
import { getIntersectionTransform } from '../utils/raycastUtils';
import { createNodeWithPositionAndNormal } from '../utils/nodeUtils';
import { EnvironmentLoadingManager } from '../common/loadingManagers';
import useMatterportViewer from '../hooks/useMatterportViewer';

import Environment, { presets } from './three-fiber/Environment';
import { StatsWindow } from './three-fiber/StatsWindow';
Expand All @@ -35,7 +36,7 @@ export const WebGLCanvasManager: React.FC = () => {

const sceneComposerId = useContext(sceneComposerIdContext);
const { isEditing, addingWidget, setAddingWidget } = useEditorState(sceneComposerId);
const { enableMatterportViewer } = useViewOptionState(sceneComposerId);
const { enableMatterportViewer } = useMatterportViewer();
const { document, getSceneNodeByRef, getSceneProperty } = useSceneDocument(sceneComposerId);
const appendSceneNode = useStore(sceneComposerId)((state) => state.appendSceneNode);
const { gl } = useThree();
Expand Down
5 changes: 3 additions & 2 deletions packages/scene-composer/src/components/panels/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { useIntl } from 'react-intl';

import { KnownComponentType } from '../../interfaces';
import { sceneComposerIdContext } from '../../common/sceneComposerIdContext';
import { ICameraComponentInternal, useStore, useViewOptionState } from '../../store';
import { ICameraComponentInternal, useStore } from '../../store';
import useActiveCamera from '../../hooks/useActiveCamera';
import useMatterportViewer from '../../hooks/useMatterportViewer';
import { findComponentByType } from '../../utils/nodeUtils';
import { getCameraSettings } from '../../utils/cameraUtils';

Expand All @@ -23,7 +24,7 @@ export const TopBar: FC = () => {
const getSceneNodeByRef = useStore(sceneComposerId)((state) => state.getSceneNodeByRef);
const getObject3DBySceneNodeRef = useStore(sceneComposerId)((state) => state.getObject3DBySceneNodeRef);
const { setActiveCameraSettings } = useActiveCamera();
const { enableMatterportViewer } = useViewOptionState(sceneComposerId);
const { enableMatterportViewer } = useMatterportViewer();
const intl = useIntl();

const cameraItems = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import { useStore, useViewOptionState } from '../../../store';
import { sceneComposerIdContext } from '../../../common/sceneComposerIdContext';
import { KnownSceneProperty } from '../../../interfaces';
import { getGlobalSettings, subscribe, unsubscribe } from '../../../common/GlobalSettings';
import { MATTERPORT_SECRET_ARN } from '../../../common/constants';
import { MATTERPORT_ERROR, MATTERPORT_SECRET_ARN } from '../../../common/constants';
import {
getMatterportConnectionList,
getUpdatedSceneInfoForConnection,
} from '../../../utils/matterportIntegrationUtils';
import { OPTIONS_PLACEHOLDER_VALUE } from '../../../common/internalConstants';
import { DisplayMessageCategory } from '../../../store/internalInterfaces';

import { MatterportTagSync } from './MatterportTagSync';

export const MatterportIntegration: React.FC = () => {
const intl = useIntl();
const sceneComposerId = useContext(sceneComposerIdContext);
const setSceneProperty = useStore(sceneComposerId)((state) => state.setSceneProperty);
const { setSceneProperty, addMessages } = useStore(sceneComposerId)((state) => state);

const [focusInput, setFocusInput] = useState(false);
const matterportModelId = useStore(sceneComposerId)((state) =>
state.getSceneProperty(KnownSceneProperty.MatterportModelId),
);
Expand All @@ -37,15 +37,19 @@ export const MatterportIntegration: React.FC = () => {
},
]);
const [selectedConnectionName, setSelectedConnectionName] = useState<string>();
const { setMatterportViewerEnabled } = useViewOptionState(sceneComposerId);
const [isValidConnection, setIsValidConnection] = useState(false);
const { setConnectionNameForMatterportViewer } = useViewOptionState(sceneComposerId);
const twinMakerSceneMetadataModule = getGlobalSettings().twinMakerSceneMetadataModule;

const updateSelectedConnectionName = useCallback(async () => {
if (twinMakerSceneMetadataModule) {
const getSceneResponse = await twinMakerSceneMetadataModule.getSceneInfo();
if (getSceneResponse && getSceneResponse.sceneMetadata && getSceneResponse.sceneMetadata[MATTERPORT_SECRET_ARN]) {
const isValidConnection = !(getSceneResponse.error && getSceneResponse.error.code === MATTERPORT_ERROR);
setIsValidConnection(isValidConnection);
setSelectedConnectionName(getSceneResponse.sceneMetadata[MATTERPORT_SECRET_ARN]);
} else {
setIsValidConnection(false);
setSelectedConnectionName(OPTIONS_PLACEHOLDER_VALUE);
}
}
Expand Down Expand Up @@ -81,9 +85,22 @@ export const MatterportIntegration: React.FC = () => {
const newConnection = event.detail.selectedOption.value;
if (twinMakerSceneMetadataModule) {
const updatedSceneInfo = await getUpdatedSceneInfoForConnection(newConnection, twinMakerSceneMetadataModule);
await twinMakerSceneMetadataModule.updateSceneInfo(updatedSceneInfo);
twinMakerSceneMetadataModule
.updateSceneInfo(updatedSceneInfo)
.then(async () => {
setSelectedConnectionName(newConnection);
const getSceneResponse = await twinMakerSceneMetadataModule.getSceneInfo();
const isValidConnection = !(getSceneResponse.error && getSceneResponse.error.code === MATTERPORT_ERROR);
setIsValidConnection(isValidConnection);
setConnectionNameForMatterportViewer(isValidConnection ? newConnection : undefined);
if (!isValidConnection && getSceneResponse.error && getSceneResponse.error.message) {
addMessages([{ category: DisplayMessageCategory.Warning, messageText: getSceneResponse.error.message }]);
}
})
.catch((error) => {
addMessages([{ category: DisplayMessageCategory.Warning, messageText: error.message }]);
});
}
setSelectedConnectionName(newConnection);
},
[twinMakerSceneMetadataModule],
);
Expand All @@ -106,8 +123,7 @@ export const MatterportIntegration: React.FC = () => {
matterportModelIdInternal !== '' ? matterportModelIdInternal : undefined,
);
}
setFocusInput(false);
}, [matterportModelIdInternal, setFocusInput]);
}, [matterportModelIdInternal]);

const onMatterportModelIdChange = useCallback(
(event) => {
Expand All @@ -122,13 +138,8 @@ export const MatterportIntegration: React.FC = () => {
const enableMatterportViewer =
!isEmpty(matterportModelIdInternal) &&
!isEmpty(selectedConnectionName) &&
selectedConnectionName !== OPTIONS_PLACEHOLDER_VALUE;

useEffect(() => {
if (!focusInput && selectedConnectionName) {
setMatterportViewerEnabled(enableMatterportViewer);
}
}, [focusInput, matterportModelIdInternal, selectedConnectionName]);
selectedConnectionName !== OPTIONS_PLACEHOLDER_VALUE &&
isValidConnection;

return (
<React.Fragment>
Expand Down Expand Up @@ -162,7 +173,6 @@ export const MatterportIntegration: React.FC = () => {
<Input
value={matterportModelIdInternal || ''}
type='text'
onFocus={() => setFocusInput(true)}
onBlur={onInputBlur}
onChange={onMatterportModelIdChange}
placeholder={intl.formatMessage({
Expand All @@ -181,7 +191,7 @@ export const MatterportIntegration: React.FC = () => {
</Box>
<Button
ariaLabel='Learn more (opens new tab)'
href='https://docs.aws.amazon.com/iot-twinmaker/latest/guide/what-is-twinmaker.html'
href='https://docs.aws.amazon.com/iot-twinmaker/latest/guide/tm-matterport-integration.html'
iconAlign='right'
iconName='external'
target='_blank'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ exports[`MatterportIntegration should render correctly 1`] = `
<div
arialabel="Learn more (opens new tab)"
data-mocked="Button"
href="https://docs.aws.amazon.com/iot-twinmaker/latest/guide/what-is-twinmaker.html"
href="https://docs.aws.amazon.com/iot-twinmaker/latest/guide/tm-matterport-integration.html"
iconalign="right"
iconname="external"
target="_blank"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,13 @@ import {
} from '../../../../interfaces';
import { sceneComposerIdContext } from '../../../../common/sceneComposerIdContext';
import { Component, LightType, ModelType } from '../../../../models/SceneModels';
import {
IColorOverlayComponentInternal,
ISceneNodeInternal,
useEditorState,
useStore,
useViewOptionState,
} from '../../../../store';
import { IColorOverlayComponentInternal, ISceneNodeInternal, useEditorState, useStore } from '../../../../store';
import { extractFileNameExtFromUrl, parseS3BucketFromArn } from '../../../../utils/pathUtils';
import { ToolbarItem } from '../../common/ToolbarItem';
import { ToolbarItemOptionRaw, ToolbarItemOptions } from '../../common/types';
import { getGlobalSettings } from '../../../../common/GlobalSettings';
import useActiveCamera from '../../../../hooks/useActiveCamera';
import useMatterportViewer from '../../../../hooks/useMatterportViewer';
import { createNodeWithTransform, findComponentByType, isEnvironmentNode } from '../../../../utils/nodeUtils';

// Note: ObjectType String is used to record metric. DO NOT change existing ids unless it's necessary.
Expand Down Expand Up @@ -85,7 +80,7 @@ export const AddObjectMenu = (): JSX.Element => {
const getSceneNodeByRef = useStore(sceneComposerId)((state) => state.getSceneNodeByRef);
const nodeMap = useStore(sceneComposerId)((state) => state.document.nodeMap);
const { setAddingWidget, getObject3DBySceneNodeRef } = useEditorState(sceneComposerId);
const { enableMatterportViewer } = useViewOptionState(sceneComposerId);
const { enableMatterportViewer } = useMatterportViewer();
const enhancedEditingEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.ENHANCED_EDITING];
const { formatMessage } = useIntl();
const { activeCameraSettings, mainCameraObject } = useActiveCamera();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useIntl, IntlShape } from 'react-intl';
import { OrbitCameraSvg, PanCameraSvg } from '../../../../assets/svgs';
import { CameraControlsType } from '../../../../interfaces';
import { sceneComposerIdContext } from '../../../../common/sceneComposerIdContext';
import { useStore, useViewOptionState } from '../../../../store';
import { useStore } from '../../../../store';
import { ToolbarItem } from '../../common/ToolbarItem';
import { ToolbarItemGroup } from '../../common/styledComponents';
import { ToolbarItemOptions } from '../../common/types';
import useMatterportViewer from '../../../../hooks/useMatterportViewer';

import { AddObjectMenu } from './AddObjectMenu';

Expand Down Expand Up @@ -56,7 +57,7 @@ export function SceneItemGroup({ isViewing = false }: SceneItemGroupProps): JSX.
const sceneComposerId = useContext(sceneComposerIdContext);
const cameraControlsType = useStore(sceneComposerId)((state) => state.cameraControlsType);
const setCameraControlsType = useStore(sceneComposerId)((state) => state.setCameraControlsType);
const { enableMatterportViewer } = useViewOptionState(sceneComposerId);
const { enableMatterportViewer } = useMatterportViewer();
const intl = useIntl();

const initialSelectedItem = useMemo(() => {
Expand Down
55 changes: 55 additions & 0 deletions packages/scene-composer/src/hooks/useMatterportViewer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { renderHook } from '@testing-library/react-hooks';

import { useStore } from '../store';

import useMatterportViewer from './useMatterportViewer';

describe('useMatterportViewer', () => {
const baseState = {
getSceneProperty: jest.fn(),
};
const createState = (connectionName?: string) => ({
...baseState,
noHistoryStates: {
...useStore('default').getState().noHistoryStates,
connectionNameForMatterportViewer: connectionName,
setConnectionNameForMatterportViewer: jest.fn(),
},
});

beforeEach(() => {
jest.clearAllMocks();
});

it('should get enableMatterportViewer as true when connectionName and model id are configured', () => {
useStore('default').setState(createState('mockConnectionName'));
baseState.getSceneProperty.mockReturnValue('mockMatterportModelId');

const enableMatterportViewer = renderHook(() => useMatterportViewer()).result.current.enableMatterportViewer;
expect(enableMatterportViewer).toEqual(true);
});

it('should get enableMatterportViewer as false when connectionName is not configured', () => {
useStore('default').setState(createState());
baseState.getSceneProperty.mockReturnValue('mockMatterportModelId');

const enableMatterportViewer = renderHook(() => useMatterportViewer()).result.current.enableMatterportViewer;
expect(enableMatterportViewer).toEqual(false);
});

it('should get enableMatterportViewer as false when model id is not configured', () => {
useStore('default').setState(createState('mockConnectionName'));
baseState.getSceneProperty.mockReturnValue(undefined);

const enableMatterportViewer = renderHook(() => useMatterportViewer()).result.current.enableMatterportViewer;
expect(enableMatterportViewer).toEqual(false);
});

it('should get enableMatterportViewer as false when connectionName and model id are not configured', () => {
useStore('default').setState(createState());
baseState.getSceneProperty.mockReturnValue(undefined);

const enableMatterportViewer = renderHook(() => useMatterportViewer()).result.current.enableMatterportViewer;
expect(enableMatterportViewer).toEqual(false);
});
});
Loading

0 comments on commit 24ca493

Please sign in to comment.