diff --git a/src/components/metadata/MetaArrayItem.js b/src/components/metadata/MetaArrayItem.js index c69a476a0..c2cdb9ba3 100644 --- a/src/components/metadata/MetaArrayItem.js +++ b/src/components/metadata/MetaArrayItem.js @@ -12,14 +12,6 @@ export class MetaArrayItem extends Component { convertField(nameAttr, type); } - handleDropdownFocus() { - findDOMNode(this.refs.wrap).classList.add('showing-dropdown'); - } - - handleDropdownBlur() { - findDOMNode(this.refs.wrap).classList.remove('showing-dropdown'); - } - handleRemoveClick() { const { removeField, namePrefix, index } = this.props; removeField(namePrefix, index); @@ -56,8 +48,6 @@ export class MetaArrayItem extends Component { parentType="array" onConvertClick={type => this.handleConvertClick(type)} onRemoveClick={() => this.handleRemoveClick()} - onDropdownFocus={() => this.handleDropdownFocus()} - onDropdownBlur={() => this.handleDropdownBlur()} /> { + this.setState(state => { + return { dropdown: !state.dropdown }; + }); + }; + + renderDropdownItems(type) { const { onConvertClick } = this.props; - onConvertClick(type); - } - handleRemoveClick() { - const { onRemoveClick } = this.props; - onRemoveClick(); + return this.fieldTypeKeys.map((ftype, i) => { + if (type !== ftype) { + const { icon, label } = this.fieldTypes[ftype]; + return ( + onConvertClick(ftype)}> + + Convert to {label} + + ); + } + }).filter(Boolean); } render() { - const { - currentType, - parentType, - onDropdownFocus, - onDropdownBlur, - } = this.props; + const { currentType, parentType, onRemoveClick } = this.props; + const sortableHandle = ( + + + + ); + + const dropdownClasses = classnames('dropdown', { + 'showing-dropdown': this.state.dropdown, + }); + return (
- {parentType == 'array' && ( - - - - )} - + {parentType == 'array' && sortableHandle} + onDropdownFocus()} - onBlur={() => onDropdownBlur()} className="meta-button" tabIndex="1" + onClick={this.toggleDropdownState} + onBlur={() => this.setState({ dropdown: false })} >
- {currentType != 'simple' && ( - this.handleTypeChange('simple')}> - Convert to Simple - - )} - {currentType != 'array' && ( - this.handleTypeChange('array')}> - Convert to List - - )} - {currentType != 'object' && ( - this.handleTypeChange('object')}> - Convert to Object - - )} - this.handleRemoveClick()} - className="remove-field" - > - Remove field + {this.renderDropdownItems(currentType)} + onRemoveClick()} className="remove-field"> + + Remove field
@@ -70,8 +89,4 @@ MetaButtons.propTypes = { parentType: PropTypes.string.isRequired, onConvertClick: PropTypes.func.isRequired, onRemoveClick: PropTypes.func.isRequired, - onDropdownFocus: PropTypes.func.isRequired, - onDropdownBlur: PropTypes.func.isRequired, }; - -export default MetaButtons; diff --git a/src/components/metadata/MetaField.js b/src/components/metadata/MetaField.js index c77f70e35..c10a25e4f 100644 --- a/src/components/metadata/MetaField.js +++ b/src/components/metadata/MetaField.js @@ -17,14 +17,6 @@ export class MetaField extends Component { convertField(nameAttr, type); } - handleDropdownFocus() { - findDOMNode(this.refs.wrap).classList.add('showing-dropdown'); - } - - handleDropdownBlur() { - findDOMNode(this.refs.wrap).classList.remove('showing-dropdown'); - } - handleKeyBlur() { const { namePrefix, fieldKey, updateFieldKey } = this.props; let currentValue = findDOMNode(this.refs.field_key).value; @@ -76,8 +68,6 @@ export class MetaField extends Component { parentType="top" onConvertClick={type => this.handleConvertClick(type)} onRemoveClick={() => this.handleRemoveClick()} - onDropdownFocus={() => this.handleDropdownFocus()} - onDropdownBlur={() => this.handleDropdownBlur()} />
this.handleConvertClick(type)} onRemoveClick={() => this.handleRemoveClick()} - onDropdownFocus={() => this.handleDropdownFocus()} - onDropdownBlur={() => this.handleDropdownBlur()} />
diff --git a/src/components/metadata/tests/metaarrayitem.spec.js b/src/components/metadata/tests/metaarrayitem.spec.js index 249bd3d91..921a4146a 100644 --- a/src/components/metadata/tests/metaarrayitem.spec.js +++ b/src/components/metadata/tests/metaarrayitem.spec.js @@ -68,15 +68,26 @@ describe('Components::MetaArrayItem', () => { expect(component.find(MetaObjectItem).length).toBe(2); }); - it('should add `showing-dropdown` class when dropdown button is focused', () => { + it('should toggle `showing-dropdown` class when dropdown button is clicked', () => { const { component, metabuttons } = setup(); let dropdownButton = metabuttons.find('.meta-button'); - dropdownButton.simulate('focus'); - expect( - component.find('.array-item-wrap').hasClass('showing-dropdown') - ).toEqual(true); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( + true + ); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').node.classList.length).toBe(1); + }); + + it('should remove `showing-dropdown` class when dropdown button loses focus', () => { + const { component, metabuttons } = setup(); + let dropdownButton = metabuttons.find('.meta-button'); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( + true + ); dropdownButton.simulate('blur'); - expect(component.find('.array-item-wrap').node.classList.length).toBe(1); + expect(component.find('.dropdown').node.classList.length).toBe(1); }); it('should call removeField when the button clicked', () => { diff --git a/src/components/metadata/tests/metabuttons.spec.js b/src/components/metadata/tests/metabuttons.spec.js index 43f2a2dd5..7087a80ab 100644 --- a/src/components/metadata/tests/metabuttons.spec.js +++ b/src/components/metadata/tests/metabuttons.spec.js @@ -4,20 +4,16 @@ import MetaButtons from '../MetaButtons'; const defaultProps = { currentType: 'simple', - parentType: 'array' + parentType: 'array', }; function setup(props = defaultProps) { const actions = { onConvertClick: jest.fn(), onRemoveClick: jest.fn(), - onDropdownFocus: jest.fn(), - onDropdownBlur: jest.fn() }; - let component = mount( - - ); + let component = mount(); return { component, @@ -25,7 +21,7 @@ function setup(props = defaultProps) { dropdownButton: component.find('.dropdown .meta-button'), sortHandle: component.find('.move'), actions, - props + props, }; } @@ -35,25 +31,21 @@ describe('Components::MetaButtons', () => { expect(sortHandle.node).toBeTruthy(); expect(convertButtons.length).toBe(3); }); + it('should not render sort handle if parentType is not array', () => { const { sortHandle } = setup({ currentType: 'simple', - parentType: 'object' + parentType: 'object', }); expect(sortHandle.node).toBeFalsy(); }); - it('should call onDropdownFocus and onDropdownBlur', () => { - const { actions, dropdownButton } = setup(); - dropdownButton.simulate('focus'); - expect(actions.onDropdownFocus).toHaveBeenCalled(); - dropdownButton.simulate('blur'); - expect(actions.onDropdownBlur).toHaveBeenCalled(); - }); + it('should call onConvertClick', () => { const { actions, convertButtons } = setup(); convertButtons.forEach(node => node.simulate('mousedown')); expect(actions.onConvertClick.mock.calls.length).toBe(2); }); + it('should call removeField', () => { const { component, actions } = setup(); let removeFieldButton = component.find('.remove-field'); diff --git a/src/components/metadata/tests/metafield.spec.js b/src/components/metadata/tests/metafield.spec.js index e570d4a58..c4f575bbc 100644 --- a/src/components/metadata/tests/metafield.spec.js +++ b/src/components/metadata/tests/metafield.spec.js @@ -76,15 +76,26 @@ describe('Components::MetaField', () => { expect(actions.updateFieldKey).toHaveBeenCalled(); }); - it('should add `showing-dropdown` class when dropdown button is focused', () => { + it('should toggle `showing-dropdown` class when dropdown button is clicked', () => { const { component, metabuttons } = setup(); let dropdownButton = metabuttons.find('.meta-button'); - dropdownButton.simulate('focus'); - expect(component.find('.metafield').hasClass('showing-dropdown')).toEqual( + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( + true + ); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').node.classList.length).toBe(1); + }); + + it('should remove `showing-dropdown` class when dropdown button loses focus', () => { + const { component, metabuttons } = setup(); + let dropdownButton = metabuttons.find('.meta-button'); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( true ); dropdownButton.simulate('blur'); - expect(component.find('.metafield').node.classList.length).toBe(1); + expect(component.find('.dropdown').node.classList.length).toBe(1); }); it('should call removeField when the button clicked', () => { diff --git a/src/components/metadata/tests/metaobjectitem.spec.js b/src/components/metadata/tests/metaobjectitem.spec.js index 1dea80829..3f7a98309 100644 --- a/src/components/metadata/tests/metaobjectitem.spec.js +++ b/src/components/metadata/tests/metaobjectitem.spec.js @@ -76,15 +76,26 @@ describe('Components::MetaObjectItem', () => { expect(actions.updateFieldKey).toHaveBeenCalled(); }); - it('should add `showing-dropdown` class when dropdown button is focused', () => { + it('should toggle `showing-dropdown` class when dropdown button is clicked', () => { const { component, metabuttons } = setup(); let dropdownButton = metabuttons.find('.meta-button'); - dropdownButton.simulate('focus'); - expect( - component.find('.object-item-wrap').hasClass('showing-dropdown') - ).toEqual(true); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( + true + ); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').node.classList.length).toBe(1); + }); + + it('should remove `showing-dropdown` class when dropdown button loses focus', () => { + const { component, metabuttons } = setup(); + let dropdownButton = metabuttons.find('.meta-button'); + dropdownButton.simulate('click'); + expect(component.find('.dropdown').hasClass('showing-dropdown')).toEqual( + true + ); dropdownButton.simulate('blur'); - expect(component.find('.object-item-wrap').node.classList.length).toBe(1); + expect(component.find('.dropdown').node.classList.length).toBe(1); }); it('should call removeField when the button clicked', () => { diff --git a/src/styles/datagui.scss b/src/styles/datagui.scss index e395b2a51..d2b08f471 100644 --- a/src/styles/datagui.scss +++ b/src/styles/datagui.scss @@ -388,9 +388,6 @@ opacity: 0; } } - .showing-dropdown { - z-index: 30; - } .date-field { float: right; right: 34px; diff --git a/src/styles/metafields.scss b/src/styles/metafields.scss index 38935c6ab..793ead25a 100644 --- a/src/styles/metafields.scss +++ b/src/styles/metafields.scss @@ -220,6 +220,11 @@ .dropdown { position: relative; cursor: pointer; + &.showing-dropdown { + .dropdown-wrap { + display: block; + } + } .meta-button { display: inline-block; width: 23px; @@ -236,11 +241,6 @@ background: $dark-orange; border-color: $dark-orange; } - &:focus { - +.dropdown-wrap { - display: block; - } - } i { margin: 0; } @@ -381,9 +381,6 @@ opacity: 0; } } - .showing-dropdown { - z-index: 30; - } .date-field { float: right; right: 34px;