From 1026cb4d607317a43bb45e0058e9762a3a5430c1 Mon Sep 17 00:00:00 2001 From: Emily Dodds Date: Mon, 7 Nov 2022 16:28:12 -0600 Subject: [PATCH] fix(composer):Scene Hierarchy radio buttons & bug fix for selection on single click (#326) * fix(composer): Implementing Scene Hierarchy radio buttons for single-click select & bug fix for selection on single click * Implementing PR feedback Co-authored-by: Emily Dodds --- packages/scene-composer/package.json | 4 +- .../anchor/__tests__}/AnchorWidget.spec.tsx | 8 +- .../__snapshots__/AnchorWidget.spec.tsx.snap | 0 .../__tests__/RadioButton.spec.tsx | 74 +++++ .../__snapshots__/RadioButton.spec.tsx.snap | 42 +++ .../src/components/RadioButton/index.tsx | 19 ++ .../components/RadioButton/radio-button.scss | 13 + .../src/components/Tree/TreeItem.tsx | 41 ++- .../Tree/{ => __tests__}/TreeItem.spec.tsx | 100 ++++-- .../__snapshots__/TreeItem.spec.tsx.snap | 131 ++++---- .../__snapshots__/tree.spec.tsx.snap | 56 ++-- .../Tree/{ => __tests__}/tree.spec.tsx | 2 +- .../src/components/Tree/tree.scss | 202 +++++------- .../SceneHierarchyDataProvider.tsx | 3 +- .../SceneHierarchyPanel.spec.tsx.snap | 2 + .../SceneHierarchyTree/SceneNodeLabel.tsx | 2 +- .../__tests__/SceneNodeLabel.specs.tsx | 58 ++-- .../SceneNodeLabel.specs.tsx.snap | 19 ++ .../components/SubModelTree/SubModelTree.scss | 2 +- .../__tests__/SubModelTree.spec.tsx | 52 +++- .../__snapshots__/SubModelTree.spec.tsx.snap | 292 +++++++++++++++++- .../layout/__snapshots__/layout.spec.tsx.snap | 1 + .../SceneHierarchyPanel/layout/index.tsx | 2 +- 23 files changed, 811 insertions(+), 314 deletions(-) rename packages/scene-composer/{tests/augmentations/components/three-fiber/anchor => src/augmentations/components/three-fiber/anchor/__tests__}/AnchorWidget.spec.tsx (91%) rename packages/scene-composer/{tests/augmentations/components/three-fiber/anchor => src/augmentations/components/three-fiber/anchor/__tests__}/__snapshots__/AnchorWidget.spec.tsx.snap (100%) create mode 100644 packages/scene-composer/src/components/RadioButton/__tests__/RadioButton.spec.tsx create mode 100644 packages/scene-composer/src/components/RadioButton/__tests__/__snapshots__/RadioButton.spec.tsx.snap create mode 100644 packages/scene-composer/src/components/RadioButton/index.tsx create mode 100644 packages/scene-composer/src/components/RadioButton/radio-button.scss rename packages/scene-composer/src/components/Tree/{ => __tests__}/TreeItem.spec.tsx (66%) rename packages/scene-composer/src/components/Tree/{ => __tests__}/__snapshots__/TreeItem.spec.tsx.snap (66%) rename packages/scene-composer/src/components/Tree/{ => __tests__}/__snapshots__/tree.spec.tsx.snap (65%) rename packages/scene-composer/src/components/Tree/{ => __tests__}/tree.spec.tsx (95%) diff --git a/packages/scene-composer/package.json b/packages/scene-composer/package.json index 1171ee748..e48192898 100644 --- a/packages/scene-composer/package.json +++ b/packages/scene-composer/package.json @@ -156,8 +156,8 @@ "global": { "lines": 77.58, "statements": 76.75, - "functions": 77.58, - "branches": 63.72, + "functions": 77.2, + "branches": 63.5, "branchesTrue": 100 } } diff --git a/packages/scene-composer/tests/augmentations/components/three-fiber/anchor/AnchorWidget.spec.tsx b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx similarity index 91% rename from packages/scene-composer/tests/augmentations/components/three-fiber/anchor/AnchorWidget.spec.tsx rename to packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx index bde4524ec..6d15794e0 100644 --- a/packages/scene-composer/tests/augmentations/components/three-fiber/anchor/AnchorWidget.spec.tsx +++ b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx @@ -3,11 +3,11 @@ import React from 'react'; import * as THREE from 'three'; import { useLoader } from '@react-three/fiber'; -import { AnchorWidget } from '../../../../../src/augmentations/components/three-fiber/anchor/AnchorWidget'; -import { DefaultAnchorStatus, KnownComponentType } from '../../../../../src'; -import { useStore } from '../../../../../src/store'; +import { AnchorWidget } from '../AnchorWidget'; +import { DefaultAnchorStatus } from '../../../../..'; +import { useStore } from '../../../../../store'; -jest.mock('../../../../../src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite', () => +jest.mock('../../../three-fiber/common/SvgIconToWidgetSprite', () => jest.fn(((data, name, alwaysVisible, props) =>
) as any), ); diff --git a/packages/scene-composer/tests/augmentations/components/three-fiber/anchor/__snapshots__/AnchorWidget.spec.tsx.snap b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap similarity index 100% rename from packages/scene-composer/tests/augmentations/components/three-fiber/anchor/__snapshots__/AnchorWidget.spec.tsx.snap rename to packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap diff --git a/packages/scene-composer/src/components/RadioButton/__tests__/RadioButton.spec.tsx b/packages/scene-composer/src/components/RadioButton/__tests__/RadioButton.spec.tsx new file mode 100644 index 000000000..4494ddf9a --- /dev/null +++ b/packages/scene-composer/src/components/RadioButton/__tests__/RadioButton.spec.tsx @@ -0,0 +1,74 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; + +import RadioButton from '../index'; + +describe('RadioButton', () => { + [ + [ + 'First Option', + { + testId: 'one', + selected: false, + toggle: () => { + return null; + }, + label: 'radio one', + }, + ], + [ + 'Second Option', + { + testId: 'two', + selected: true, + toggle: () => { + return null; + }, + label: 'radio two', + }, + ], + [ + 'Third Option', + { + testId: 'three', + selected: false, + toggle: () => { + return null; + }, + label: 'radio three', + }, + ], + [ + 'Fourth Option', + { + testId: 'four', + selected: false, + toggle: () => { + return null; + }, + label: 'radio four', + }, + ], + [ + 'Fifth Option', + { + testId: 'five', + selected: false, + toggle: () => { + return null; + }, + label: 'radio five', + }, + ], + ].forEach((item) => { + it(`it should render the ${item[0]} as a radio button`, () => { + const data = item[1] as any; + const { selected, testId, toggle, label } = data; + + const { getByTestId } = render(); + const radioBtn: any = getByTestId(testId); + + expect(radioBtn).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/scene-composer/src/components/RadioButton/__tests__/__snapshots__/RadioButton.spec.tsx.snap b/packages/scene-composer/src/components/RadioButton/__tests__/__snapshots__/RadioButton.spec.tsx.snap new file mode 100644 index 000000000..26a7aa7d4 --- /dev/null +++ b/packages/scene-composer/src/components/RadioButton/__tests__/__snapshots__/RadioButton.spec.tsx.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RadioButton it should render the Fifth Option as a radio button 1`] = ` + +`; + +exports[`RadioButton it should render the First Option as a radio button 1`] = ` + +`; + +exports[`RadioButton it should render the Fourth Option as a radio button 1`] = ` + +`; + +exports[`RadioButton it should render the Second Option as a radio button 1`] = ` + +`; + +exports[`RadioButton it should render the Third Option as a radio button 1`] = ` + +`; diff --git a/packages/scene-composer/src/components/RadioButton/index.tsx b/packages/scene-composer/src/components/RadioButton/index.tsx new file mode 100644 index 000000000..e2c46c9ce --- /dev/null +++ b/packages/scene-composer/src/components/RadioButton/index.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; + +import './radio-button.scss'; + +export interface RadioButtonProps { + checked?: boolean; + label?: string; + selected?: boolean; + testId?: string; + toggle: (e: any) => void; +} + +const RadioButton: FC = ({ label, selected, testId, toggle }) => { + return ; +}; + +RadioButton.displayName = 'RadioButton'; + +export default RadioButton; diff --git a/packages/scene-composer/src/components/RadioButton/radio-button.scss b/packages/scene-composer/src/components/RadioButton/radio-button.scss new file mode 100644 index 000000000..3a29b13c1 --- /dev/null +++ b/packages/scene-composer/src/components/RadioButton/radio-button.scss @@ -0,0 +1,13 @@ +input[type="radio"] { + margin-right: 1rem; + + // styled to match Polaris: https://polaris.a2z.com/components/radio-group/ + &:checked { + appearance: none; + background-color: #fff; + color: #fff; + border: 4px solid #00a1c9; + border-radius: 50%; + padding: 3px; + } +} \ No newline at end of file diff --git a/packages/scene-composer/src/components/Tree/TreeItem.tsx b/packages/scene-composer/src/components/Tree/TreeItem.tsx index f233cfe6d..0341911eb 100644 --- a/packages/scene-composer/src/components/Tree/TreeItem.tsx +++ b/packages/scene-composer/src/components/Tree/TreeItem.tsx @@ -1,9 +1,14 @@ -import { Button, Checkbox } from '@awsui/components-react'; +import { Button } from '@awsui/components-react'; import React, { ComponentPropsWithRef, FC, ReactNode, useCallback } from 'react'; +import RadioButton from '../RadioButton'; +import { useStore } from '../../store'; +import { useSceneComposerId } from '../../common/sceneComposerIdContext'; + export type SelectionMode = 'single' | 'multi'; interface TreeItemInnerProps { + label?: string; selected?: boolean; selectable?: boolean; className?: string; @@ -23,33 +28,45 @@ export interface TreeItemProps extends TreeItemInnerProps, ComponentPropsWithRef const TreeItemInner: FC = ({ children, + label, onSelected = /* istanbul ignore next */ () => {}, selectable = true, selected = false, className = '', onActivated = () => {}, }) => { + const sceneComposerId = useSceneComposerId(); + const setSelectedSceneNodeRef = useStore(sceneComposerId).getState().setSelectedSceneNodeRef; + + const selectFromChildren = () => { + (children as any)?.forEach((child) => { + return child ? setSelectedSceneNodeRef(child.props?.objectRef) : null; + }); + }; + const toggle = useCallback( (e) => { - onSelected(!selected, e); + return (children) => + children.every((child) => child === true) ? selectFromChildren() : onSelected(!selected, e); }, [selected, onSelected], ); return ( -
{selectable && ( - + <> + {children} - + )} {!selectable && children} -
+ ); }; @@ -88,7 +105,13 @@ const TreeItem = React.forwardRef( role='treeitem' {...props} > - + {expandable && (
- + +