diff --git a/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx b/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx index 43c51543d3..f32e8a80e7 100644 --- a/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx +++ b/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx @@ -27,6 +27,8 @@ const DataListCell = styled(PFDataListCell)` const Switch = styled(PFSwitch)` display: flex; flex-wrap: no-wrap; + /* workaround PF bug; used in calculating switch width: */ + --pf-c-switch__toggle-icon--Offset: 0.125rem; `; function NotificationListItem(props) { diff --git a/awx/ui_next/src/components/NotificationList/__snapshots__/NotificationListItem.test.jsx.snap b/awx/ui_next/src/components/NotificationList/__snapshots__/NotificationListItem.test.jsx.snap index ee9f735fec..6b8d98afcc 100644 --- a/awx/ui_next/src/components/NotificationList/__snapshots__/NotificationListItem.test.jsx.snap +++ b/awx/ui_next/src/components/NotificationList/__snapshots__/NotificationListItem.test.jsx.snap @@ -331,9 +331,9 @@ exports[` initially renders succe "componentStyle": ComponentStyle { "componentId": "NotificationListItem__Switch-w674ng-1", "isStatic": true, - "lastClassName": "hbNxaH", + "lastClassName": "hfzRow", "rules": Array [ - "display:flex;flex-wrap:no-wrap;", + "display:flex;flex-wrap:no-wrap;--pf-c-switch__toggle-icon--Offset:0.125rem;", ], }, "displayName": "NotificationListItem__Switch", @@ -356,7 +356,7 @@ exports[` initially renders succe > initially renders succe componentProps={ Object { "aria-label": "Toggle notification start", - "className": "NotificationListItem__Switch-w674ng-1 hbNxaH", + "className": "NotificationListItem__Switch-w674ng-1 hfzRow", "id": "notification-9000-started-toggle", "isChecked": false, "isDisabled": false, @@ -382,7 +382,7 @@ exports[` initially renders succe > initially renders succe } > initially renders succe "componentStyle": ComponentStyle { "componentId": "NotificationListItem__Switch-w674ng-1", "isStatic": true, - "lastClassName": "hbNxaH", + "lastClassName": "hfzRow", "rules": Array [ - "display:flex;flex-wrap:no-wrap;", + "display:flex;flex-wrap:no-wrap;--pf-c-switch__toggle-icon--Offset:0.125rem;", ], }, "displayName": "NotificationListItem__Switch", @@ -476,7 +476,7 @@ exports[` initially renders succe > initially renders succe componentProps={ Object { "aria-label": "Toggle notification success", - "className": "NotificationListItem__Switch-w674ng-1 hbNxaH", + "className": "NotificationListItem__Switch-w674ng-1 hfzRow", "id": "notification-9000-success-toggle", "isChecked": false, "isDisabled": false, @@ -502,7 +502,7 @@ exports[` initially renders succe > initially renders succe } > initially renders succe "componentStyle": ComponentStyle { "componentId": "NotificationListItem__Switch-w674ng-1", "isStatic": true, - "lastClassName": "hbNxaH", + "lastClassName": "hfzRow", "rules": Array [ - "display:flex;flex-wrap:no-wrap;", + "display:flex;flex-wrap:no-wrap;--pf-c-switch__toggle-icon--Offset:0.125rem;", ], }, "displayName": "NotificationListItem__Switch", @@ -596,7 +596,7 @@ exports[` initially renders succe > initially renders succe componentProps={ Object { "aria-label": "Toggle notification failure", - "className": "NotificationListItem__Switch-w674ng-1 hbNxaH", + "className": "NotificationListItem__Switch-w674ng-1 hfzRow", "id": "notification-9000-error-toggle", "isChecked": false, "isDisabled": false, @@ -622,7 +622,7 @@ exports[` initially renders succe > initially renders succe } > { + if (!element || !element.current.contains(e.target)) { + setIsOpen(false); + } + }; + + useEffect(() => { + document.addEventListener('click', toggle, false); + return () => { + document.removeEventListener('click', toggle); + }; + }, []); + + return ( + + setIsOpen(!isOpen)} />} + dropdownItems={[ + + {i18n._(t`Job Template`)} + , + + {i18n._(t`Workflow Template`)} + , + ]} + /> + + ); +} + +export { TemplateAddButton as _TemplateAddButton }; +export default withI18n()(withRouter(TemplateAddButton)); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateAddButton.test.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateAddButton.test.jsx new file mode 100644 index 0000000000..1a0e75e29e --- /dev/null +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateAddButton.test.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { mountWithContexts } from '@testUtils/enzymeHelpers'; +import TemplateAddButton from './TemplateAddButton'; + +describe('', () => { + test('should be closed initially', () => { + const wrapper = mountWithContexts(); + expect(wrapper.find('Dropdown').prop('isOpen')).toEqual(false); + }); + + test('should render two links', () => { + const wrapper = mountWithContexts(); + wrapper.find('button').simulate('click'); + expect(wrapper.find('Dropdown').prop('isOpen')).toEqual(true); + expect(wrapper.find('Link')).toHaveLength(2); + }); + + test('should close when button re-clicked', () => { + const wrapper = mountWithContexts(); + wrapper.find('button').simulate('click'); + expect(wrapper.find('Dropdown').prop('isOpen')).toEqual(true); + wrapper.find('button').simulate('click'); + expect(wrapper.find('Dropdown').prop('isOpen')).toEqual(false); + }); +}); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index f4618956dc..68e2bb7400 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -1,15 +1,8 @@ import React, { Component } from 'react'; -import { withRouter, Link } from 'react-router-dom'; +import { withRouter } from 'react-router-dom'; import { withI18n } from '@lingui/react'; - import { t } from '@lingui/macro'; -import { - Card, - PageSection, - Dropdown, - DropdownItem, - DropdownPosition, -} from '@patternfly/react-core'; +import { Card, PageSection } from '@patternfly/react-core'; import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api'; import AlertModal from '@components/AlertModal'; @@ -17,11 +10,11 @@ import DatalistToolbar from '@components/DataListToolbar'; import ErrorDetail from '@components/ErrorDetail'; import PaginatedDataList, { ToolbarDeleteButton, - ToolbarAddButton, } from '@components/PaginatedDataList'; import { getQSConfig, parseQueryString } from '@util/qs'; import TemplateListItem from './TemplateListItem'; +import TemplateAddButton from './TemplateAddButton'; // The type value in const QS_CONFIG below does not have a space between job_template and // workflow_job_template so the params sent to the API match what the api expects. @@ -43,7 +36,6 @@ class TemplatesList extends Component { selected: [], templates: [], itemCount: 0, - isAddOpen: false, }; this.loadTemplates = this.loadTemplates.bind(this); @@ -51,7 +43,6 @@ class TemplatesList extends Component { this.handleSelect = this.handleSelect.bind(this); this.handleTemplateDelete = this.handleTemplateDelete.bind(this); this.handleDeleteErrorClose = this.handleDeleteErrorClose.bind(this); - this.handleAddToggle = this.handleAddToggle.bind(this); } componentDidMount() { @@ -89,21 +80,6 @@ class TemplatesList extends Component { } } - handleAddToggle(e) { - const { isAddOpen } = this.state; - document.addEventListener('click', this.handleAddToggle, false); - - if (this.node && this.node.contains(e.target) && isAddOpen) { - document.removeEventListener('click', this.handleAddToggle, false); - this.setState({ isAddOpen: false }); - } else if (this.node && this.node.contains(e.target) && !isAddOpen) { - this.setState({ isAddOpen: true }); - } else { - this.setState({ isAddOpen: false }); - document.removeEventListener('click', this.handleAddToggle, false); - } - } - async handleTemplateDelete() { const { selected, itemCount } = this.state; @@ -178,7 +154,6 @@ class TemplatesList extends Component { templates, itemCount, selected, - isAddOpen, actions, } = this.state; const { match, i18n } = this.props; @@ -231,35 +206,7 @@ class TemplatesList extends Component { itemsToDelete={selected} pluralizedItemName="Templates" />, - canAdd && ( - { - this.node = node; - }} - key="add" - > - - } - dropdownItems={[ - - - {i18n._(t`Job Template`)} - - , - - - {i18n._(t`Workflow Template`)} - - , - ]} - /> - - ), + canAdd && , ]} /> )} @@ -273,35 +220,7 @@ class TemplatesList extends Component { isSelected={selected.some(row => row.id === template.id)} /> )} - emptyStateControls={ - canAdd && ( - { - this.node = node; - }} - key="add" - > - } - dropdownItems={[ - - - {i18n._(t`Job Template`)} - - , - - - {i18n._(t`Workflow Template`)} - - , - ]} - /> - - ) - } + emptyStateControls={canAdd && } />