From 4ebc2573a33d7fbd528f56fdc5afaa3377f3061c Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Tue, 18 Feb 2020 10:40:18 -0500 Subject: [PATCH] Remove DataList component overrides --- awx/ui_next/src/app.scss | 4 - .../CheckboxListItem/CheckboxListItem.jsx | 31 +- .../components/DataListCell/DataListCell.jsx | 14 - .../DataListCell/DataListCell.test.jsx | 11 - .../src/components/DataListCell/index.js | 1 - .../DataListCheck/DataListCheck.jsx | 15 - .../DataListCheck/DataListCheck.test.jsx | 10 - .../src/components/DataListCheck/index.js | 1 - .../DataListRadio/DataListRadio.jsx | 47 -- .../DataListRadio/DataListRadio.test.jsx | 36 - .../src/components/DataListRadio/index.js | 1 - .../DataListToolbar/DataListToolbar.jsx | 36 +- .../NotificationList/NotificationListItem.jsx | 103 ++- .../NotificationListItem.test.jsx.snap | 698 +++++++----------- .../components/SelectedList/SelectedList.jsx | 3 +- .../src/components/Sparkline/Sparkline.jsx | 8 +- awx/ui_next/src/index.jsx | 1 - .../CredentialList/CredentialList.jsx | 6 +- .../CredentialList/CredentialListItem.jsx | 42 +- .../src/screens/Host/HostList/HostList.jsx | 11 +- .../screens/Host/HostList/HostListItem.jsx | 86 ++- .../InventoryGroups/InventoryGroupItem.jsx | 30 +- .../InventoryGroups/InventoryGroupsList.jsx | 14 +- .../InventoryHosts/InventoryHostItem.jsx | 81 +- .../InventoryHosts/InventoryHostList.jsx | 14 +- .../Inventory/InventoryList/InventoryList.jsx | 2 +- .../InventoryList/InventoryListItem.jsx | 41 +- .../src/screens/Job/JobList/JobList.test.jsx | 6 + .../src/screens/Job/JobList/JobListItem.jsx | 45 +- .../OrganizationList/OrganizationList.jsx | 6 +- .../OrganizationList.test.jsx | 3 + .../OrganizationList/OrganizationListItem.jsx | 51 +- .../Project/ProjectList/ProjectList.jsx | 11 +- .../Project/ProjectList/ProjectListItem.jsx | 85 ++- .../src/screens/Team/TeamList/TeamList.jsx | 11 +- .../screens/Team/TeamList/TeamList.test.jsx | 3 + .../screens/Team/TeamList/TeamListItem.jsx | 42 +- .../Template/TemplateList/TemplateList.jsx | 6 +- .../TemplateList/TemplateListItem.jsx | 78 +- .../Modals/NodeModals/NodeModal.test.jsx | 10 +- .../NodeModals/NodeTypeStep/NodeTypeStep.jsx | 6 +- .../NodeTypeStep/NodeTypeStep.test.jsx | 8 +- .../VisualizerToolbar.jsx | 16 +- .../src/screens/User/UserList/UserList.jsx | 11 +- .../screens/User/UserList/UserListItem.jsx | 41 +- 45 files changed, 788 insertions(+), 998 deletions(-) delete mode 100644 awx/ui_next/src/app.scss delete mode 100644 awx/ui_next/src/components/DataListCell/DataListCell.jsx delete mode 100644 awx/ui_next/src/components/DataListCell/DataListCell.test.jsx delete mode 100644 awx/ui_next/src/components/DataListCell/index.js delete mode 100644 awx/ui_next/src/components/DataListCheck/DataListCheck.jsx delete mode 100644 awx/ui_next/src/components/DataListCheck/DataListCheck.test.jsx delete mode 100644 awx/ui_next/src/components/DataListCheck/index.js delete mode 100644 awx/ui_next/src/components/DataListRadio/DataListRadio.jsx delete mode 100644 awx/ui_next/src/components/DataListRadio/DataListRadio.test.jsx delete mode 100644 awx/ui_next/src/components/DataListRadio/index.js diff --git a/awx/ui_next/src/app.scss b/awx/ui_next/src/app.scss deleted file mode 100644 index 6da11a0e7a..0000000000 --- a/awx/ui_next/src/app.scss +++ /dev/null @@ -1,4 +0,0 @@ -// https://github.com/patternfly/patternfly-react/issues/1294 -#app { - height: 100%; -} diff --git a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx index 2616cf15cd..0213d7d113 100644 --- a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx +++ b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx @@ -6,19 +6,21 @@ import { DataListItemCells, DataListCell, DataListCheck, + Radio, } from '@patternfly/react-core'; -import DataListRadio from '@components/DataListRadio'; const CheckboxListItem = ({ + isDisabled = false, + isRadio = false, + isSelected = false, itemId, - name, label, - isSelected, - onSelect, + name, onDeselect, - isRadio, + onSelect, }) => { - const CheckboxRadio = isRadio ? DataListRadio : DataListCheck; + const CheckboxRadio = isRadio ? Radio : DataListCheck; + return ( (props.righthalf ? '16px' : '8px')}; - @media screen and (min-width: 768px) { - padding-bottom: 0; - justify-content: ${props => (props.lastcolumn ? 'flex-end' : 'inherit')}; - } -`; - -export default DataListCell; diff --git a/awx/ui_next/src/components/DataListCell/DataListCell.test.jsx b/awx/ui_next/src/components/DataListCell/DataListCell.test.jsx deleted file mode 100644 index 55ec0b3018..0000000000 --- a/awx/ui_next/src/components/DataListCell/DataListCell.test.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { mountWithContexts } from '@testUtils/enzymeHelpers'; - -import DataListCell from './DataListCell'; - -describe('DataListCell', () => { - test('renders without failing', () => { - const wrapper = mountWithContexts(); - expect(wrapper).toHaveLength(1); - }); -}); diff --git a/awx/ui_next/src/components/DataListCell/index.js b/awx/ui_next/src/components/DataListCell/index.js deleted file mode 100644 index d925b63c7d..0000000000 --- a/awx/ui_next/src/components/DataListCell/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './DataListCell'; diff --git a/awx/ui_next/src/components/DataListCheck/DataListCheck.jsx b/awx/ui_next/src/components/DataListCheck/DataListCheck.jsx deleted file mode 100644 index 30817989cf..0000000000 --- a/awx/ui_next/src/components/DataListCheck/DataListCheck.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import { DataListCheck as PFDataListCheck } from '@patternfly/react-core'; -import styled from 'styled-components'; - -PFDataListCheck.displayName = 'PFDataListCheck'; -export default styled(PFDataListCheck)` - padding-top: 18px; - @media screen and (min-width: 768px) { - padding-top: 16px; - justify-content: ${props => (props.lastcolumn ? 'flex-end' : 'inherit')}; - .pf-c-data-list__check { - display: flex; - align-items: center; - } - } -`; diff --git a/awx/ui_next/src/components/DataListCheck/DataListCheck.test.jsx b/awx/ui_next/src/components/DataListCheck/DataListCheck.test.jsx deleted file mode 100644 index f2414374fc..0000000000 --- a/awx/ui_next/src/components/DataListCheck/DataListCheck.test.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import DataListCheck from './DataListCheck'; - -describe('DataListCheck', () => { - test('renders the expected content', () => { - const wrapper = mount(); - expect(wrapper).toHaveLength(1); - }); -}); diff --git a/awx/ui_next/src/components/DataListCheck/index.js b/awx/ui_next/src/components/DataListCheck/index.js deleted file mode 100644 index cdb8b6137c..0000000000 --- a/awx/ui_next/src/components/DataListCheck/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './DataListCheck'; diff --git a/awx/ui_next/src/components/DataListRadio/DataListRadio.jsx b/awx/ui_next/src/components/DataListRadio/DataListRadio.jsx deleted file mode 100644 index bccb1a3efe..0000000000 --- a/awx/ui_next/src/components/DataListRadio/DataListRadio.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from 'react'; -import { string, bool, func } from 'prop-types'; - -function DataListRadio({ - className = '', - onChange, - isValid = true, - isDisabled = false, - isChecked = null, - checked = null, - ...props -}) { - return ( -
-
- onChange(event.currentTarget.checked, event)} - aria-invalid={!isValid} - disabled={isDisabled} - checked={isChecked || checked} - /> -
-
- ); -} -DataListRadio.propTypes = { - className: string, - isValid: bool, - isDisabled: bool, - isChecked: bool, - checked: bool, - onChange: func, - 'aria-labelledby': string, -}; -DataListRadio.defaultProps = { - className: '', - isValid: true, - isDisabled: false, - isChecked: false, - checked: false, - onChange: () => {}, - 'aria-labelledby': '', -}; - -export default DataListRadio; diff --git a/awx/ui_next/src/components/DataListRadio/DataListRadio.test.jsx b/awx/ui_next/src/components/DataListRadio/DataListRadio.test.jsx deleted file mode 100644 index b8fa2e4135..0000000000 --- a/awx/ui_next/src/components/DataListRadio/DataListRadio.test.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { mountWithContexts } from '@testUtils/enzymeHelpers'; -import DataListRadio from './DataListRadio'; - -describe('DataListRadio', () => { - test('should call onChange', () => { - const onChange = jest.fn(); - const wrapper = mountWithContexts(); - wrapper.find('input[type="radio"]').prop('onChange')({ - currentTarget: { checked: true }, - }); - expect(onChange).toHaveBeenCalledWith(true, { - currentTarget: { checked: true }, - }); - }); - - test('should pass props to correct children', () => { - const onChange = jest.fn(); - const wrapper = mountWithContexts( - - ); - const div = wrapper.find('.pf-c-data-list__item-control'); - const input = wrapper.find('input[type="radio"]'); - - expect(div.prop('className')).toEqual('pf-c-data-list__item-control foo'); - expect(input.prop('disabled')).toBe(true); - expect(input.prop('checked')).toBe(true); - expect(input.prop('aria-invalid')).toBe(false); - }); -}); diff --git a/awx/ui_next/src/components/DataListRadio/index.js b/awx/ui_next/src/components/DataListRadio/index.js deleted file mode 100644 index c8f5b6d345..0000000000 --- a/awx/ui_next/src/components/DataListRadio/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './DataListRadio'; diff --git a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx index 0d5563a6f2..ce1f53f053 100644 --- a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx +++ b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx @@ -7,10 +7,10 @@ import styled from 'styled-components'; import { SearchIcon } from '@patternfly/react-icons'; import { DataToolbar, - DataToolbarContent, - DataToolbarGroup, - DataToolbarToggleGroup, + DataToolbarContent as _DataToolbarContent, + DataToolbarGroup as _DataToolbarGroup, DataToolbarItem, + DataToolbarToggleGroup, } from '@patternfly/react-core/dist/umd/experimental'; import ExpandCollapse from '../ExpandCollapse'; import Search from '../Search'; @@ -18,20 +18,12 @@ import Sort from '../Sort'; import { SearchColumns, SortColumns, QSConfig } from '@types'; -const AdditionalControlsWrapper = styled.div` - display: flex; - flex-grow: 1; - justify-content: flex-end; - align-items: center; - - & > :not(:first-child) { - margin-left: 20px; - } +const DataToolbarContent = styled(_DataToolbarContent)` + --pf-c-data-toolbar__content--PaddingLeft: 24px; + --pf-c-data-toolbar__content--PaddingRight: 8px; `; - -const AdditionalControlsDataToolbarGroup = styled(DataToolbarGroup)` - margin-left: auto; - margin-right: 0 !important; +const DataToolbarGroup = styled(_DataToolbarGroup)` + --pf-c-data-toolbar__group--spacer: 24px; `; class DataListToolbar extends React.Component { @@ -102,13 +94,11 @@ class DataListToolbar extends React.Component { )} - - - - {additionalControls} - - - + + {additionalControls.map(control => ( + {control} + ))} + ); diff --git a/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx b/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx index fb4e80cfa9..6a2c1f8437 100644 --- a/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx +++ b/awx/ui_next/src/components/NotificationList/NotificationListItem.jsx @@ -4,24 +4,20 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Link } from 'react-router-dom'; import { + DataListAction as _DataListAction, + DataListCell, DataListItem, - DataListItemRow, DataListItemCells, - DataListCell as PFDataListCell, + DataListItemRow, Switch, } from '@patternfly/react-core'; - import styled from 'styled-components'; -const DataListCell = styled(PFDataListCell)` - display: flex; - justify-content: ${props => (props.righthalf ? 'flex-start' : 'inherit')}; - padding-bottom: ${props => (props.righthalf ? '16px' : '8px')}; - - @media screen and (min-width: 768px) { - justify-content: ${props => (props.righthalf ? 'flex-end' : 'inherit')}; - padding-bottom: 0; - } +const DataListAction = styled(_DataListAction)` + align-items: center; + display: grid; + grid-gap: 16px; + grid-template-columns: repeat(3, max-content); `; function NotificationListItem(props) { @@ -51,7 +47,6 @@ function NotificationListItem(props) { to={{ pathname: detailUrl, }} - css="margin-right: 1.5em;" > {notification.name} @@ -61,51 +56,47 @@ function NotificationListItem(props) { {typeLabels[notification.notification_type]} , - - - toggleNotification( - notification.id, - startedTurnedOn, - 'started' - ) - } - aria-label={i18n._(t`Toggle notification start`)} - /> - - toggleNotification( - notification.id, - successTurnedOn, - 'success' - ) - } - aria-label={i18n._(t`Toggle notification success`)} - /> - - toggleNotification(notification.id, errorTurnedOn, 'error') - } - aria-label={i18n._(t`Toggle notification failure`)} - /> - , ]} /> + + + toggleNotification(notification.id, startedTurnedOn, 'started') + } + aria-label={i18n._(t`Toggle notification start`)} + /> + + toggleNotification(notification.id, successTurnedOn, 'success') + } + aria-label={i18n._(t`Toggle notification success`)} + /> + + toggleNotification(notification.id, errorTurnedOn, 'error') + } + aria-label={i18n._(t`Toggle notification failure`)} + /> +
); 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 c531e44c0c..2ec6011b1d 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 @@ -42,7 +42,7 @@ exports[` initially renders succe + initially renders succe Foo - , - + , + Slack - , - - - - - , + , ] } key=".0" @@ -99,453 +68,324 @@ exports[` initially renders succe
- - - -
- - - - - - - Foo - - - - - - -
-
-
-
- + + + +
+ + - - -
- Slack -
-
-
- - +
+ + + + + - - -
- - + - - + + + + + + + + - + - - + + + + + + + + - + - -
-
-
- - - + Failure + + + + + + + +
+
+
diff --git a/awx/ui_next/src/components/SelectedList/SelectedList.jsx b/awx/ui_next/src/components/SelectedList/SelectedList.jsx index 60045a04b0..6fd0eb9da1 100644 --- a/awx/ui_next/src/components/SelectedList/SelectedList.jsx +++ b/awx/ui_next/src/components/SelectedList/SelectedList.jsx @@ -15,6 +15,7 @@ const Split = styled(PFSplit)` const SplitLabelItem = styled(SplitItem)` font-weight: bold; + margin-right: 32px; word-break: initial; `; @@ -39,7 +40,7 @@ class SelectedList extends Component { return ( - {label} + {label} {selected.map(item => diff --git a/awx/ui_next/src/components/Sparkline/Sparkline.jsx b/awx/ui_next/src/components/Sparkline/Sparkline.jsx index d9346758c3..d0aabceb95 100644 --- a/awx/ui_next/src/components/Sparkline/Sparkline.jsx +++ b/awx/ui_next/src/components/Sparkline/Sparkline.jsx @@ -13,6 +13,10 @@ import { JOB_TYPE_URL_SEGMENTS } from '@constants'; const Link = styled(props => <_Link {...props} />)` margin-right: 5px; `; + +const Wrapper = styled.div` + display: inline-flex; +`; /* eslint-enable react/jsx-pascal-case */ const Sparkline = ({ i18n, jobs }) => { @@ -32,13 +36,15 @@ const Sparkline = ({ i18n, jobs }) => { ); - return jobs.map(job => ( + const statusIcons = jobs.map(job => ( )); + + return {statusIcons}; }; Sparkline.propTypes = { diff --git a/awx/ui_next/src/index.jsx b/awx/ui_next/src/index.jsx index 06d5245d81..f2abdbc1ff 100644 --- a/awx/ui_next/src/index.jsx +++ b/awx/ui_next/src/index.jsx @@ -5,7 +5,6 @@ import { I18n } from '@lingui/react'; import { t } from '@lingui/macro'; import '@patternfly/react-core/dist/styles/base.css'; -import './app.scss'; import { isAuthenticated } from '@util/auth'; import Background from '@components/Background'; diff --git a/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx b/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx index ada903e709..40d7a65657 100644 --- a/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx +++ b/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx @@ -125,9 +125,9 @@ function CredentialList({ i18n }) { itemsToDelete={selected} pluralizedItemName={i18n._(t`Credentials`)} />, - canAdd && ( - - ), + ...(canAdd + ? [] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Credential/CredentialList/CredentialListItem.jsx b/awx/ui_next/src/screens/Credential/CredentialList/CredentialListItem.jsx index f5f6cff512..9b519bfcb1 100644 --- a/awx/ui_next/src/screens/Credential/CredentialList/CredentialListItem.jsx +++ b/awx/ui_next/src/screens/Credential/CredentialList/CredentialListItem.jsx @@ -5,24 +5,18 @@ import { t } from '@lingui/macro'; import { Link } from 'react-router-dom'; import { Button, + DataListAction, + DataListCell, DataListCheck, DataListItem, DataListItemRow, - DataListItemCells as _DataListItemCells, + DataListItemCells, Tooltip, } from '@patternfly/react-core'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; -import styled from 'styled-components'; import { Credential } from '@types'; -const DataListItemCells = styled(_DataListItemCells)` - ${DataListCell}:first-child { - flex-grow: 2; - } -`; - function CredentialListItem({ credential, detailUrl, @@ -56,21 +50,25 @@ function CredentialListItem({ {credential.summary_fields.credential_type.name} , - - {canEdit && ( - - - - )} - , ]} /> + + {canEdit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Host/HostList/HostList.jsx b/awx/ui_next/src/screens/Host/HostList/HostList.jsx index 5d1dbbdfbd..0edc224d30 100644 --- a/awx/ui_next/src/screens/Host/HostList/HostList.jsx +++ b/awx/ui_next/src/screens/Host/HostList/HostList.jsx @@ -224,9 +224,14 @@ class HostsList extends Component { itemsToDelete={selected} pluralizedItemName={i18n._(t`Hosts`)} />, - canAdd ? ( - - ) : null, + ...(canAdd + ? [ + , + ] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Host/HostList/HostListItem.jsx b/awx/ui_next/src/screens/Host/HostList/HostListItem.jsx index 72baf5e8f9..72f4047229 100644 --- a/awx/ui_next/src/screens/Host/HostList/HostListItem.jsx +++ b/awx/ui_next/src/screens/Host/HostList/HostListItem.jsx @@ -4,6 +4,8 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Button, + DataListAction as _DataListAction, + DataListCell, DataListCheck, DataListItem, DataListItemRow, @@ -14,9 +16,16 @@ import { import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; import { Sparkline } from '@components/Sparkline'; import { Host } from '@types'; +import styled from 'styled-components'; + +const DataListAction = styled(_DataListAction)` + align-items: center; + display: grid; + grid-gap: 24px; + grid-template-columns: min-content 40px; +`; class HostListItem extends React.Component { static propTypes = { @@ -65,9 +74,7 @@ class HostListItem extends React.Component { {host.summary_fields.inventory && ( - - {i18n._(t`Inventory`)} - + {i18n._(t`Inventory`)} )} , - - - onToggleHost(host)} - aria-label={i18n._(t`Toggle host`)} - /> - - , - - {host.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + + onToggleHost(host)} + aria-label={i18n._(t`Toggle host`)} + /> + + {host.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupItem.jsx b/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupItem.jsx index 55ef6ccdce..77f9ccab26 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupItem.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupItem.jsx @@ -6,17 +6,17 @@ import { Group } from '@types'; import { Button, + DataListAction, + DataListCell, DataListCheck, DataListItem, - DataListItemRow, DataListItemCells, + DataListItemRow, Tooltip, } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; - function InventoryGroupItem({ i18n, group, @@ -39,22 +39,26 @@ function InventoryGroupItem({ /> + {group.name} , - - {group.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {group.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupsList.jsx b/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupsList.jsx index 96f9d64327..f511d83156 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupsList.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryGroups/InventoryGroupsList.jsx @@ -238,12 +238,14 @@ function InventoryGroupsList({ i18n, location, match }) { , - canAdd && ( - - ), + ...(canAdd + ? [ + , + ] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostItem.jsx b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostItem.jsx index 89a19fec6f..12e1281cb4 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostItem.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostItem.jsx @@ -4,19 +4,27 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Button, + DataListAction as _DataListAction, + DataListCell, DataListCheck, DataListItem, - DataListItemRow, DataListItemCells, + DataListItemRow, Switch, Tooltip, } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; - -import DataListCell from '@components/DataListCell'; import { Sparkline } from '@components/Sparkline'; import { Host } from '@types'; +import styled from 'styled-components'; + +const DataListAction = styled(_DataListAction)` + align-items: center; + display: grid; + grid-gap: 24px; + grid-template-columns: min-content 40px; +`; function InventoryHostItem(props) { const { @@ -56,41 +64,42 @@ function InventoryHostItem(props) { , - - - toggleHost(host)} - aria-label={i18n._(t`Toggle host`)} - /> - - , - - {host.summary_fields.user_capabilities?.edit && ( - - - - )} - , ]} /> + + + toggleHost(host)} + aria-label={i18n._(t`Toggle host`)} + /> + + {host.summary_fields.user_capabilities?.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostList.jsx b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostList.jsx index 1a4a7e35a7..d59890040c 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostList.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHostList.jsx @@ -165,12 +165,14 @@ function InventoryHostList({ i18n, location, match }) { itemsToDelete={selected} pluralizedItemName={i18n._(t`Hosts`)} />, - canAdd && ( - - ), + ...(canAdd + ? [ + , + ] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryList.jsx b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryList.jsx index ef7ec6ff1b..6884adf4f7 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryList.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryList.jsx @@ -208,7 +208,7 @@ class InventoriesList extends Component { itemsToDelete={selected} pluralizedItemName="Inventories" />, - canAdd && addButton, + ...(canAdd ? [addButton] : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx index 60092cc06c..ea5e445994 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx @@ -3,17 +3,18 @@ import { string, bool, func } from 'prop-types'; import { withI18n } from '@lingui/react'; import { Button, + DataListAction, + DataListCell, DataListCheck, DataListItem, - DataListItemRow, DataListItemCells, + DataListItemRow, Tooltip, } from '@patternfly/react-core'; import { t } from '@lingui/macro'; import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; import { Inventory } from '@types'; class InventoryListItem extends React.Component { @@ -52,25 +53,27 @@ class InventoryListItem extends React.Component { ? i18n._(t`Smart Inventory`) : i18n._(t`Inventory`)} , - - {inventory.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {inventory.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Job/JobList/JobList.test.jsx b/awx/ui_next/src/screens/Job/JobList/JobList.test.jsx index 7379b4079a..75632f2f7b 100644 --- a/awx/ui_next/src/screens/Job/JobList/JobList.test.jsx +++ b/awx/ui_next/src/screens/Job/JobList/JobList.test.jsx @@ -23,6 +23,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + start: true, }, }, }, @@ -34,6 +35,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + start: true, }, }, }, @@ -45,6 +47,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + start: true, }, }, }, @@ -56,6 +59,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + start: true, }, }, }, @@ -67,6 +71,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + edit: true, }, }, }, @@ -78,6 +83,7 @@ const mockResults = [ summary_fields: { user_capabilities: { delete: true, + edit: true, }, }, }, diff --git a/awx/ui_next/src/screens/Job/JobList/JobListItem.jsx b/awx/ui_next/src/screens/Job/JobList/JobListItem.jsx index fe93aa04e1..5620e446ad 100644 --- a/awx/ui_next/src/screens/Job/JobList/JobListItem.jsx +++ b/awx/ui_next/src/screens/Job/JobList/JobListItem.jsx @@ -5,6 +5,7 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Button, + DataListAction, DataListCell, DataListCheck, DataListItem, @@ -20,28 +21,26 @@ import { formatDateString } from '@util/dates'; import { JOB_TYPE_URL_SEGMENTS } from '@constants'; const PaddedIcon = styled(StatusIcon)` - margin-right: 20px; + margin: 6px 20px 0 0; `; class JobListItem extends Component { render() { const { i18n, job, isSelected, onSelect } = this.props; + const labelId = `check-action-${job.id}`; return ( - + + {job.status && } {formatDateString(job.finished)} , - - {job.type !== 'system_job' && - job.summary_fields.user_capabilities.start && ( - - - {({ handleRelaunch }) => ( - - )} - - - )} - , ]} /> + {job.type !== 'system_job' && + job.summary_fields?.user_capabilities?.start && ( + + + + {({ handleRelaunch }) => ( + + )} + + + + )} ); diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 65564f5bd0..1b116e3096 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -146,9 +146,9 @@ function OrganizationsList({ i18n }) { itemsToDelete={selected} pluralizedItemName="Organizations" />, - canAdd ? ( - - ) : null, + ...(canAdd + ? [] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.test.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.test.jsx index 5c7fb53966..8151033123 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.test.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.test.jsx @@ -23,6 +23,7 @@ const mockOrganizations = { }, user_capabilities: { delete: true, + edit: true, }, }, }, @@ -37,6 +38,7 @@ const mockOrganizations = { }, user_capabilities: { delete: true, + edit: true, }, }, }, @@ -51,6 +53,7 @@ const mockOrganizations = { }, user_capabilities: { delete: true, + edit: true, }, }, }, diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationListItem.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationListItem.jsx index fe99e91716..f2b1a4f8ee 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationListItem.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationListItem.jsx @@ -5,36 +5,29 @@ import { t } from '@lingui/macro'; import { Badge as PFBadge, Button, + DataListAction, + DataListCell, DataListCheck, DataListItem, - DataListItemRow, DataListItemCells, + DataListItemRow, Tooltip, } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; import { Organization } from '@types'; const Badge = styled(PFBadge)` - align-items: center; - display: flex; - justify-content: center; - margin-left: 10px; + margin-left: 8px; `; const ListGroup = styled.span` - display: flex; - margin-left: 40px; + margin-left: 24px; - @media screen and (min-width: 768px) { - margin-left: 20px; - - &:first-of-type { - margin-left: 0; - } + &:first-of-type { + margin-left: 0; } `; @@ -82,21 +75,25 @@ function OrganizationListItem({ , - - {organization.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {organization.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Project/ProjectList/ProjectList.jsx b/awx/ui_next/src/screens/Project/ProjectList/ProjectList.jsx index 1f65b7da5a..4311f17a61 100644 --- a/awx/ui_next/src/screens/Project/ProjectList/ProjectList.jsx +++ b/awx/ui_next/src/screens/Project/ProjectList/ProjectList.jsx @@ -206,9 +206,14 @@ class ProjectsList extends Component { itemsToDelete={selected} pluralizedItemName={i18n._(t`Projects`)} />, - canAdd ? ( - - ) : null, + ...(canAdd + ? [ + , + ] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Project/ProjectList/ProjectListItem.jsx b/awx/ui_next/src/screens/Project/ProjectList/ProjectListItem.jsx index 993293785f..ae01789d57 100644 --- a/awx/ui_next/src/screens/Project/ProjectList/ProjectListItem.jsx +++ b/awx/ui_next/src/screens/Project/ProjectList/ProjectListItem.jsx @@ -3,6 +3,8 @@ import { string, bool, func } from 'prop-types'; import { withI18n } from '@lingui/react'; import { Button, + DataListAction as _DataListAction, + DataListCell, DataListCheck, DataListItem, DataListItemRow, @@ -12,14 +14,24 @@ import { import { t } from '@lingui/macro'; import { Link } from 'react-router-dom'; import { PencilAltIcon, SyncIcon } from '@patternfly/react-icons'; +import styled from 'styled-components'; import ClipboardCopyButton from '@components/ClipboardCopyButton'; -import DataListCell from '@components/DataListCell'; import ProjectSyncButton from '../shared/ProjectSyncButton'; import { StatusIcon } from '@components/Sparkline'; import { toTitleCase } from '@util/strings'; import { Project } from '@types'; +const PaddedIcon = styled(StatusIcon)` + margin: 6px 20px 0 0; +`; + +const DataListAction = styled(_DataListAction)` + align-items: center; + display: grid; + grid-gap: 16px; + grid-template-columns: repeat(2, 40px); +`; class ProjectListItem extends React.Component { static propTypes = { project: Project.isRequired, @@ -72,7 +84,7 @@ class ProjectListItem extends React.Component { /> + {project.summary_fields.last_job && ( - )} - + {project.name} , @@ -103,7 +111,7 @@ class ProjectListItem extends React.Component { ? i18n._(t`Manual`) : toTitleCase(project.scm_type)} , - + {project.scm_revision.substring(0, 7)} {project.scm_revision ? ( ) : null} , - - {project.summary_fields.user_capabilities.start && ( - - - {handleSync => ( - - )} - - - )} - , - - {project.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {project.summary_fields.user_capabilities.start && ( + + + {handleSync => ( + + )} + + + )} + {project.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Team/TeamList/TeamList.jsx b/awx/ui_next/src/screens/Team/TeamList/TeamList.jsx index 91de161404..e3912890e6 100644 --- a/awx/ui_next/src/screens/Team/TeamList/TeamList.jsx +++ b/awx/ui_next/src/screens/Team/TeamList/TeamList.jsx @@ -193,9 +193,14 @@ class TeamsList extends Component { itemsToDelete={selected} pluralizedItemName={i18n._(t`Teams`)} />, - canAdd ? ( - - ) : null, + ...(canAdd + ? [ + , + ] + : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Team/TeamList/TeamList.test.jsx b/awx/ui_next/src/screens/Team/TeamList/TeamList.test.jsx index 2eb816a5f6..063b958a70 100644 --- a/awx/ui_next/src/screens/Team/TeamList/TeamList.test.jsx +++ b/awx/ui_next/src/screens/Team/TeamList/TeamList.test.jsx @@ -17,6 +17,7 @@ const mockAPITeamsList = { summary_fields: { user_capabilities: { delete: true, + edit: true, }, }, }, @@ -27,6 +28,7 @@ const mockAPITeamsList = { summary_fields: { user_capabilities: { delete: true, + edit: true, }, }, }, @@ -37,6 +39,7 @@ const mockAPITeamsList = { summary_fields: { user_capabilities: { delete: true, + edit: true, }, }, }, diff --git a/awx/ui_next/src/screens/Team/TeamList/TeamListItem.jsx b/awx/ui_next/src/screens/Team/TeamList/TeamListItem.jsx index ff5da73316..0b1e66e9d3 100644 --- a/awx/ui_next/src/screens/Team/TeamList/TeamListItem.jsx +++ b/awx/ui_next/src/screens/Team/TeamList/TeamListItem.jsx @@ -4,16 +4,17 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Button, + DataListAction, + DataListCell, DataListCheck, DataListItem, - DataListItemRow, DataListItemCells, + DataListItemRow, Tooltip, } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; import { Team } from '@types'; class TeamListItem extends React.Component { @@ -27,6 +28,7 @@ class TeamListItem extends React.Component { render() { const { team, isSelected, onSelect, detailUrl, i18n } = this.props; const labelId = `check-action-${team.id}`; + return ( @@ -38,7 +40,7 @@ class TeamListItem extends React.Component { /> + {team.name} @@ -46,9 +48,7 @@ class TeamListItem extends React.Component { {team.summary_fields.organization && ( - - {i18n._(t`Organization`)} - + {i18n._(t`Organization`)} @@ -57,21 +57,25 @@ class TeamListItem extends React.Component { )} , - - {team.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {team.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 2b2239d0fd..04f19229c2 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -121,21 +121,25 @@ function TemplateList({ i18n }) { const canAddWFJT = wfjtActions && Object.prototype.hasOwnProperty.call(wfjtActions, 'POST'); const addButtonOptions = []; + if (canAddJT) { addButtonOptions.push({ label: i18n._(t`Template`), url: `/templates/job_template/add/`, }); } + if (canAddWFJT) { addButtonOptions.push({ label: i18n._(t`Workflow Template`), url: `/templates/workflow_job_template/add/`, }); } + const addButton = ( ); + return ( <> @@ -215,7 +219,7 @@ function TemplateList({ i18n }) { itemsToDelete={selected} pluralizedItemName="Templates" />, - (canAddJT || canAddWFJT) && addButton, + ...(canAddJT || canAddWFJT ? [addButton] : []), ]} /> )} diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.jsx index b9c2debc50..05cc5c6439 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.jsx @@ -2,6 +2,8 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Button, + DataListAction as _DataListAction, + DataListCell, DataListCheck, DataListItem, DataListItemRow, @@ -16,12 +18,20 @@ import { RocketIcon, } from '@patternfly/react-icons'; -import DataListCell from '@components/DataListCell'; import LaunchButton from '@components/LaunchButton'; import { Sparkline } from '@components/Sparkline'; import { toTitleCase } from '@util/strings'; +import styled from 'styled-components'; + +const DataListAction = styled(_DataListAction)` + align-items: center; + display: grid; + grid-gap: 16px; + grid-template-columns: repeat(2, 40px); +`; function TemplateListItem({ i18n, template, isSelected, onSelect, detailUrl }) { + const labelId = `check-action-${template.id}`; const canLaunch = template.summary_fields.user_capabilities.start; const missingResourceIcon = @@ -31,16 +41,13 @@ function TemplateListItem({ i18n, template, isSelected, onSelect, detailUrl }) { !template.ask_inventory_on_launch)); return ( - + , - - {canLaunch && template.type === 'job_template' && ( - - - {({ handleLaunch }) => ( - - )} - - - )} - , - - {template.summary_fields.user_capabilities.edit && ( - - - - )} - , ]} /> + + {canLaunch && template.type === 'job_template' && ( + + + {({ handleLaunch }) => ( + + )} + + + )} + {template.summary_fields.user_capabilities.edit && ( + + + + )} + ); diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx index 5cd9840b57..3b5d96b381 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx @@ -109,7 +109,7 @@ describe('NodeModal', () => { wrapper.find('button#next-node-modal').simulate('click'); }); wrapper.update(); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); await act(async () => { wrapper.find('button#next-node-modal').simulate('click'); }); @@ -136,7 +136,7 @@ describe('NodeModal', () => { wrapper.find('AnsibleSelect').prop('onChange')(null, 'project_sync'); }); wrapper.update(); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); await act(async () => { wrapper.find('button#next-node-modal').simulate('click'); }); @@ -166,7 +166,7 @@ describe('NodeModal', () => { ); }); wrapper.update(); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); await act(async () => { wrapper.find('button#next-node-modal').simulate('click'); }); @@ -193,7 +193,7 @@ describe('NodeModal', () => { ); }); wrapper.update(); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); await act(async () => { wrapper.find('button#next-node-modal').simulate('click'); }); @@ -396,7 +396,7 @@ describe('NodeModal', () => { ); }); wrapper.update(); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); await act(async () => { wrapper.find('button#next-node-modal').simulate('click'); }); diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.jsx index a8a3f73fee..bd5d38f3cb 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.jsx @@ -7,7 +7,6 @@ import { Formik, Field } from 'formik'; import { Form, FormGroup, TextInput } from '@patternfly/react-core'; import FormRow from '@components/FormRow'; import AnsibleSelect from '@components/AnsibleSelect'; -import VerticalSeperator from '@components/VerticalSeparator'; import InventorySourcesList from './InventorySourcesList'; import JobTemplatesList from './JobTemplatesList'; import ProjectsList from './ProjectsList'; @@ -47,9 +46,8 @@ function NodeTypeStep({ }) { return ( <> -
- {i18n._(t`Node Type`)} - +
+ {i18n._(t`Node Type`)}
{ wrapper.update(); expect(wrapper.find('AnsibleSelect').prop('value')).toBe('job_template'); expect(wrapper.find('JobTemplatesList').length).toBe(1); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 1, name: 'Test Job Template', @@ -119,7 +119,7 @@ describe('NodeTypeStep', () => { wrapper.update(); expect(wrapper.find('AnsibleSelect').prop('value')).toBe('project_sync'); expect(wrapper.find('ProjectsList').length).toBe(1); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 1, name: 'Test Project', @@ -146,7 +146,7 @@ describe('NodeTypeStep', () => { 'inventory_source_sync' ); expect(wrapper.find('InventorySourcesList').length).toBe(1); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 1, name: 'Test Inventory Source', @@ -173,7 +173,7 @@ describe('NodeTypeStep', () => { 'workflow_job_template' ); expect(wrapper.find('WorkflowJobTemplatesList').length).toBe(1); - wrapper.find('DataListRadio').simulate('click'); + wrapper.find('Radio').simulate('click'); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 1, name: 'Test Workflow Job Template', diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx index 4712c7b481..8785ba6979 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx @@ -6,7 +6,12 @@ import { import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { func, shape } from 'prop-types'; -import { Badge as PFBadge, Button, Tooltip } from '@patternfly/react-core'; +import { + Badge as PFBadge, + Button, + Title, + Tooltip, +} from '@patternfly/react-core'; import { BookIcon, CompassIcon, @@ -15,7 +20,6 @@ import { TrashAltIcon, WrenchIcon, } from '@patternfly/react-icons'; -import VerticalSeparator from '@components/VerticalSeparator'; import styled from 'styled-components'; const Badge = styled(PFBadge)` @@ -51,15 +55,12 @@ function VisualizerToolbar({ i18n, onClose, onSave, template }) { return (
-
- {template.name} -
+ {template.name}
{i18n._(t`Total Nodes`)}
{totalNodes} - - - - - )} - , ]} /> + + {user.summary_fields.user_capabilities.edit && ( + + + + )} + );