mirror of
https://github.com/ansible/awx.git
synced 2026-03-05 10:41:05 -03:30
Merge pull request #5982 from marshmalien/5866-remove-datalist-alert-modal
Remove DataList component overrides Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
2
awx/ui_next/dist/index.html
vendored
2
awx/ui_next/dist/index.html
vendored
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app" style="height: 100%"></div>
|
||||||
<script src="/bundle.js"></script>
|
<script src="/bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ class App extends Component {
|
|||||||
/>
|
/>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={configError}
|
isOpen={configError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleConfigErrorClose}
|
onClose={this.handleConfigErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
// https://github.com/patternfly/patternfly-react/issues/1294
|
|
||||||
#app {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// data list overrides
|
|
||||||
//
|
|
||||||
|
|
||||||
.pf-c-data-list {
|
|
||||||
--pf-global--target-size--MinHeight: 32px;
|
|
||||||
--pf-global--target-size--MinWidth: 32px;
|
|
||||||
--pf-global--FontSize--md: 14px;
|
|
||||||
|
|
||||||
.pf-c-badge:not(:last-child),
|
|
||||||
.pf-c-switch:not(:last-child) {
|
|
||||||
margin-right: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-data-list__item-row {
|
|
||||||
--pf-c-data-list__item-row--PaddingRight: 20px;
|
|
||||||
--pf-c-data-list__item-row--PaddingLeft: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-data-list__item-content {
|
|
||||||
--pf-c-data-list__item-content--PaddingBottom: 16px;
|
|
||||||
|
|
||||||
min-height: 59px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-data-list__item-control {
|
|
||||||
--pf-c-data-list__item-control--PaddingTop: 16px;
|
|
||||||
--pf-c-data-list__item-control--MarginRight: 8px;
|
|
||||||
--pf-c-data-list__item-control--PaddingBottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-data-list__item {
|
|
||||||
--pf-c-data-list__item--PaddingLeft: 20px;
|
|
||||||
--pf-c-data-list__item--PaddingRight: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-data-list__cell {
|
|
||||||
--pf-c-data-list__cell--PaddingTop: 16px;
|
|
||||||
--pf-c-data-list__cell-cell--PaddingTop: 16px;
|
|
||||||
|
|
||||||
&.pf-c-data-list__cell--divider {
|
|
||||||
--pf-c-data-list__cell-cell--MarginRight: 0;
|
|
||||||
--pf-c-data-list__cell--PaddingTop: 12px;
|
|
||||||
flex-grow: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// AlertModal styles
|
|
||||||
//
|
|
||||||
|
|
||||||
.at-c-alertModal.pf-c-modal-box {
|
|
||||||
border: 0;
|
|
||||||
border-left: 56px solid black;
|
|
||||||
|
|
||||||
.at-c-alertModal__icon {
|
|
||||||
position: absolute;
|
|
||||||
font-size: 23px;
|
|
||||||
top: 28px;
|
|
||||||
left: -39px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal--warning.pf-c-modal-box {
|
|
||||||
border-color: var(--pf-global--warning-color--100);
|
|
||||||
|
|
||||||
.pf-c-title {
|
|
||||||
color: var(--pf-global--warning-color--200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal__icon {
|
|
||||||
color: var(--pf-global--warning-color--200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal--danger.pf-c-modal-box {
|
|
||||||
border-color: var(--pf-global--danger-color--100);
|
|
||||||
|
|
||||||
.pf-c-title {
|
|
||||||
color: var(--pf-global--danger-color--200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal__icon {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal--info.pf-c-modal-box {
|
|
||||||
border-color: var(--pf-global--info-color--100);
|
|
||||||
|
|
||||||
.pf-c-title {
|
|
||||||
color: var(--pf-global--info-color--200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal__icon {
|
|
||||||
color: var(--pf-global--info-color--200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal--success.pf-c-modal-box {
|
|
||||||
border-color: var(--pf-global--success-color--100);
|
|
||||||
|
|
||||||
.pf-c-title {
|
|
||||||
color: var(--pf-global--success-color--200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-alertModal__icon {
|
|
||||||
color: var(--pf-global--success-color--200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +1,47 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Modal, Title } from '@patternfly/react-core';
|
||||||
import { Modal } from '@patternfly/react-core';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ExclamationTriangleIcon,
|
|
||||||
ExclamationCircleIcon,
|
|
||||||
InfoCircleIcon,
|
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
|
ExclamationCircleIcon,
|
||||||
|
ExclamationTriangleIcon,
|
||||||
|
InfoCircleIcon,
|
||||||
|
TimesCircleIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const getIcon = variant => {
|
const Header = styled.div`
|
||||||
let icon;
|
display: flex;
|
||||||
if (variant === 'warning') {
|
svg {
|
||||||
icon = <ExclamationTriangleIcon className="at-c-alertModal__icon" />;
|
margin-right: 16px;
|
||||||
} else if (variant === 'danger') {
|
|
||||||
icon = <ExclamationCircleIcon className="at-c-alertModal__icon" />;
|
|
||||||
}
|
}
|
||||||
if (variant === 'info') {
|
`;
|
||||||
icon = <InfoCircleIcon className="at-c-alertModal__icon" />;
|
|
||||||
}
|
export default ({ isOpen = null, title, variant, children, ...props }) => {
|
||||||
if (variant === 'success') {
|
const variantIcons = {
|
||||||
icon = <CheckCircleIcon className="at-c-alertModal__icon" />;
|
danger: <ExclamationCircleIcon size="lg" css="color: #c9190b" />,
|
||||||
}
|
error: <TimesCircleIcon size="lg" css="color: #c9190b" />,
|
||||||
return icon;
|
info: <InfoCircleIcon size="lg" css="color: #73bcf7" />,
|
||||||
};
|
success: <CheckCircleIcon size="lg" css="color: #92d400" />,
|
||||||
|
warning: <ExclamationTriangleIcon size="lg" css="color: #f0ab00" />,
|
||||||
|
};
|
||||||
|
|
||||||
|
const customHeader = (
|
||||||
|
<Header>
|
||||||
|
{variant ? variantIcons[variant] : null}
|
||||||
|
<Title size="2xl">{title}</Title>
|
||||||
|
</Header>
|
||||||
|
);
|
||||||
|
|
||||||
export default ({ variant, children, ...props }) => {
|
|
||||||
const { isOpen = null } = props;
|
|
||||||
props.isOpen = Boolean(isOpen);
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isLarge
|
header={customHeader}
|
||||||
className={`awx-c-modal${variant &&
|
isFooterLeftAligned
|
||||||
` at-c-alertModal at-c-alertModal--${variant}`}`}
|
isOpen={Boolean(isOpen)}
|
||||||
|
isSmall
|
||||||
|
title={title}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
{getIcon(variant)}
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import AlertModal from './AlertModal';
|
|||||||
|
|
||||||
describe('AlertModal', () => {
|
describe('AlertModal', () => {
|
||||||
test('renders the expected content', () => {
|
test('renders the expected content', () => {
|
||||||
const wrapper = mount(<AlertModal title="Danger!" />);
|
const wrapper = mount(
|
||||||
|
<AlertModal title="Danger!">Are you sure?</AlertModal>
|
||||||
|
);
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(wrapper).toHaveLength(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,19 +6,21 @@ import {
|
|||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
DataListCell,
|
DataListCell,
|
||||||
DataListCheck,
|
DataListCheck,
|
||||||
|
Radio,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import DataListRadio from '@components/DataListRadio';
|
|
||||||
|
|
||||||
const CheckboxListItem = ({
|
const CheckboxListItem = ({
|
||||||
|
isDisabled = false,
|
||||||
|
isRadio = false,
|
||||||
|
isSelected = false,
|
||||||
itemId,
|
itemId,
|
||||||
name,
|
|
||||||
label,
|
label,
|
||||||
isSelected,
|
name,
|
||||||
onSelect,
|
|
||||||
onDeselect,
|
onDeselect,
|
||||||
isRadio,
|
onSelect,
|
||||||
}) => {
|
}) => {
|
||||||
const CheckboxRadio = isRadio ? DataListRadio : DataListCheck;
|
const CheckboxRadio = isRadio ? Radio : DataListCheck;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataListItem
|
<DataListItem
|
||||||
key={itemId}
|
key={itemId}
|
||||||
@@ -27,11 +29,14 @@ const CheckboxListItem = ({
|
|||||||
>
|
>
|
||||||
<DataListItemRow>
|
<DataListItemRow>
|
||||||
<CheckboxRadio
|
<CheckboxRadio
|
||||||
id={`selected-${itemId}`}
|
aria-label={`check-action-item-${itemId}`}
|
||||||
checked={isSelected}
|
|
||||||
onChange={isSelected ? onDeselect : onSelect}
|
|
||||||
aria-labelledby={`check-action-item-${itemId}`}
|
aria-labelledby={`check-action-item-${itemId}`}
|
||||||
|
checked={isSelected}
|
||||||
|
disabled={isDisabled}
|
||||||
|
id={`selected-${itemId}`}
|
||||||
|
isChecked={isSelected}
|
||||||
name={name}
|
name={name}
|
||||||
|
onChange={isSelected ? onDeselect : onSelect}
|
||||||
value={itemId}
|
value={itemId}
|
||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
@@ -53,12 +58,12 @@ const CheckboxListItem = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
CheckboxListItem.propTypes = {
|
CheckboxListItem.propTypes = {
|
||||||
itemId: PropTypes.number.isRequired,
|
|
||||||
name: PropTypes.string.isRequired,
|
|
||||||
label: PropTypes.string.isRequired,
|
|
||||||
isSelected: PropTypes.bool.isRequired,
|
isSelected: PropTypes.bool.isRequired,
|
||||||
onSelect: PropTypes.func.isRequired,
|
itemId: PropTypes.number.isRequired,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
onDeselect: PropTypes.func.isRequired,
|
onDeselect: PropTypes.func.isRequired,
|
||||||
|
onSelect: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CheckboxListItem;
|
export default CheckboxListItem;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React, { useState } from 'react';
|
|||||||
import { string, func, bool, number } from 'prop-types';
|
import { string, func, bool, number } from 'prop-types';
|
||||||
import { Button, Split, SplitItem } from '@patternfly/react-core';
|
import { Button, Split, SplitItem } from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import ButtonGroup from '@components/ButtonGroup';
|
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
|
import ButtonGroup from './ButtonGroup';
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
function formatJson(jsonString) {
|
function formatJson(jsonString) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { oneOf, func } from 'prop-types';
|
import { oneOf, func } from 'prop-types';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Button } from '@patternfly/react-core';
|
import { Button } from '@patternfly/react-core';
|
||||||
import ButtonGroup from '../ButtonGroup';
|
import ButtonGroup from './ButtonGroup';
|
||||||
|
|
||||||
const SmallButton = styled(Button)`
|
const SmallButton = styled(Button)`
|
||||||
padding: 3px 8px;
|
padding: 3px 8px;
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { Link, Redirect } from 'react-router-dom';
|
import { Link, Redirect } from 'react-router-dom';
|
||||||
import { bool, instanceOf } from 'prop-types';
|
import { bool, instanceOf } from 'prop-types';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import {
|
import {
|
||||||
Title,
|
Title,
|
||||||
EmptyState as PFEmptyState,
|
EmptyState,
|
||||||
EmptyStateIcon,
|
EmptyStateIcon,
|
||||||
EmptyStateBody,
|
EmptyStateBody,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
@@ -14,11 +13,6 @@ import { ExclamationTriangleIcon } from '@patternfly/react-icons';
|
|||||||
import { RootAPI } from '@api';
|
import { RootAPI } from '@api';
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
|
|
||||||
const EmptyState = styled(PFEmptyState)`
|
|
||||||
width: var(--pf-c-empty-state--m-lg--MaxWidth);
|
|
||||||
margin: 0 auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
await RootAPI.logout();
|
await RootAPI.logout();
|
||||||
window.location.replace('/#/login');
|
window.location.replace('/#/login');
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import { DataListCell as PFDataListCell } from '@patternfly/react-core';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const DataListCell = styled(PFDataListCell)`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-bottom: ${props => (props.righthalf ? '16px' : '8px')};
|
|
||||||
@media screen and (min-width: 768px) {
|
|
||||||
padding-bottom: 0;
|
|
||||||
justify-content: ${props => (props.lastcolumn ? 'flex-end' : 'inherit')};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default DataListCell;
|
|
||||||
@@ -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(<DataListCell />);
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default } from './DataListCell';
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@@ -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(<DataListCheck checked aria-labelledby="Checkbox" />);
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default } from './DataListCheck';
|
|
||||||
@@ -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 (
|
|
||||||
<div className={`pf-c-data-list__item-control ${className}`}>
|
|
||||||
<div className="pf-c-data-list__check">
|
|
||||||
<input
|
|
||||||
{...props}
|
|
||||||
type="radio"
|
|
||||||
onChange={event => onChange(event.currentTarget.checked, event)}
|
|
||||||
aria-invalid={!isValid}
|
|
||||||
disabled={isDisabled}
|
|
||||||
checked={isChecked || checked}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
@@ -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(<DataListRadio onChange={onChange} />);
|
|
||||||
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(
|
|
||||||
<DataListRadio
|
|
||||||
onChange={onChange}
|
|
||||||
className="foo"
|
|
||||||
isValid
|
|
||||||
isDisabled
|
|
||||||
checked
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default } from './DataListRadio';
|
|
||||||
@@ -7,10 +7,10 @@ import styled from 'styled-components';
|
|||||||
import { SearchIcon } from '@patternfly/react-icons';
|
import { SearchIcon } from '@patternfly/react-icons';
|
||||||
import {
|
import {
|
||||||
DataToolbar,
|
DataToolbar,
|
||||||
DataToolbarContent,
|
DataToolbarContent as _DataToolbarContent,
|
||||||
DataToolbarGroup,
|
DataToolbarGroup as _DataToolbarGroup,
|
||||||
DataToolbarToggleGroup,
|
|
||||||
DataToolbarItem,
|
DataToolbarItem,
|
||||||
|
DataToolbarToggleGroup,
|
||||||
} from '@patternfly/react-core/dist/umd/experimental';
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
import ExpandCollapse from '../ExpandCollapse';
|
import ExpandCollapse from '../ExpandCollapse';
|
||||||
import Search from '../Search';
|
import Search from '../Search';
|
||||||
@@ -18,27 +18,12 @@ import Sort from '../Sort';
|
|||||||
|
|
||||||
import { SearchColumns, SortColumns, QSConfig } from '@types';
|
import { SearchColumns, SortColumns, QSConfig } from '@types';
|
||||||
|
|
||||||
const AdditionalControlsWrapper = styled.div`
|
const DataToolbarContent = styled(_DataToolbarContent)`
|
||||||
display: flex;
|
--pf-c-data-toolbar__content--PaddingLeft: 24px;
|
||||||
flex-grow: 1;
|
--pf-c-data-toolbar__content--PaddingRight: 8px;
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
& > :not(:first-child) {
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
const DataToolbarGroup = styled(_DataToolbarGroup)`
|
||||||
const AdditionalControlsDataToolbarGroup = styled(DataToolbarGroup)`
|
--pf-c-data-toolbar__group--spacer: 24px;
|
||||||
margin-left: auto;
|
|
||||||
margin-right: 0 !important;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DataToolbarSeparator = styled(DataToolbarItem)`
|
|
||||||
width: 1px !important;
|
|
||||||
height: 30px !important;
|
|
||||||
margin-left: 3px !important;
|
|
||||||
margin-right: 10px !important;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class DataListToolbar extends React.Component {
|
class DataListToolbar extends React.Component {
|
||||||
@@ -80,7 +65,6 @@ class DataListToolbar extends React.Component {
|
|||||||
id="select-all"
|
id="select-all"
|
||||||
/>
|
/>
|
||||||
</DataToolbarItem>
|
</DataToolbarItem>
|
||||||
<DataToolbarSeparator variant="separator" />
|
|
||||||
</DataToolbarGroup>
|
</DataToolbarGroup>
|
||||||
)}
|
)}
|
||||||
<DataToolbarToggleGroup toggleIcon={<SearchIcon />} breakpoint="lg">
|
<DataToolbarToggleGroup toggleIcon={<SearchIcon />} breakpoint="lg">
|
||||||
@@ -110,13 +94,11 @@ class DataListToolbar extends React.Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</DataToolbarGroup>
|
</DataToolbarGroup>
|
||||||
<AdditionalControlsDataToolbarGroup>
|
<DataToolbarGroup css="margin-left: auto">
|
||||||
<DataToolbarItem>
|
{additionalControls.map(control => (
|
||||||
<AdditionalControlsWrapper>
|
<DataToolbarItem key={control.key}>{control}</DataToolbarItem>
|
||||||
{additionalControls}
|
))}
|
||||||
</AdditionalControlsWrapper>
|
</DataToolbarGroup>
|
||||||
</DataToolbarItem>
|
|
||||||
</AdditionalControlsDataToolbarGroup>
|
|
||||||
</DataToolbarContent>
|
</DataToolbarContent>
|
||||||
</DataToolbar>
|
</DataToolbar>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Button } from '@patternfly/react-core';
|
import { Button } from '@patternfly/react-core';
|
||||||
import AlertModal from '@components/AlertModal';
|
import AlertModal from '@components/AlertModal';
|
||||||
import { CardActionsRow } from '@components/Card';
|
|
||||||
|
|
||||||
function DeleteButton({
|
function DeleteButton({
|
||||||
onConfirm,
|
onConfirm,
|
||||||
@@ -29,26 +28,28 @@ function DeleteButton({
|
|||||||
title={modalTitle}
|
title={modalTitle}
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onClose={() => setIsOpen(false)}
|
onClose={() => setIsOpen(false)}
|
||||||
>
|
actions={[
|
||||||
{i18n._(t`Are you sure you want to delete:`)}
|
|
||||||
<br />
|
|
||||||
<strong>{name}</strong>
|
|
||||||
<CardActionsRow>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
aria-label={i18n._(t`Cancel`)}
|
|
||||||
onClick={() => setIsOpen(false)}
|
|
||||||
>
|
|
||||||
{i18n._(t`Cancel`)}
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
|
key="delete"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
aria-label={i18n._(t`Delete`)}
|
aria-label={i18n._(t`Delete`)}
|
||||||
onClick={onConfirm}
|
onClick={onConfirm}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</Button>
|
</Button>,
|
||||||
</CardActionsRow>
|
<Button
|
||||||
|
key="cancel"
|
||||||
|
variant="secondary"
|
||||||
|
aria-label={i18n._(t`Cancel`)}
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Cancel`)}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{i18n._(t`Are you sure you want to delete:`)}
|
||||||
|
<br />
|
||||||
|
<strong>{name}</strong>
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class LaunchButton extends React.Component {
|
|||||||
{launchError && (
|
{launchError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={launchError}
|
isOpen={launchError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleLaunchErrorClose}
|
onClose={this.handleLaunchErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { CredentialsAPI, CredentialTypesAPI } from '@api';
|
|||||||
import AnsibleSelect from '@components/AnsibleSelect';
|
import AnsibleSelect from '@components/AnsibleSelect';
|
||||||
import { FieldTooltip } from '@components/FormField';
|
import { FieldTooltip } from '@components/FormField';
|
||||||
import CredentialChip from '@components/CredentialChip';
|
import CredentialChip from '@components/CredentialChip';
|
||||||
import VerticalSeperator from '@components/VerticalSeparator';
|
|
||||||
import { getQSConfig, parseQueryString } from '@util/qs';
|
import { getQSConfig, parseQueryString } from '@util/qs';
|
||||||
import Lookup from './Lookup';
|
import Lookup from './Lookup';
|
||||||
import OptionsList from './shared/OptionsList';
|
import OptionsList from './shared/OptionsList';
|
||||||
@@ -97,8 +96,9 @@ function MultiCredentialsLookup(props) {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
{credentialTypes && credentialTypes.length > 0 && (
|
{credentialTypes && credentialTypes.length > 0 && (
|
||||||
<ToolbarItem css=" display: flex; align-items: center;">
|
<ToolbarItem css=" display: flex; align-items: center;">
|
||||||
<div css="flex: 0 0 25%;">{i18n._(t`Selected Category`)}</div>
|
<div css="flex: 0 0 25%; margin-right: 32px">
|
||||||
<VerticalSeperator />
|
{i18n._(t`Selected Category`)}
|
||||||
|
</div>
|
||||||
<AnsibleSelect
|
<AnsibleSelect
|
||||||
css="flex: 1 1 75%;"
|
css="flex: 1 1 75%;"
|
||||||
id="multiCredentialsLookUp-select"
|
id="multiCredentialsLookUp-select"
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ class NotificationList extends Component {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
isOpen={toggleError && !toggleLoading}
|
isOpen={toggleError && !toggleLoading}
|
||||||
onClose={this.handleNotificationErrorClose}
|
onClose={this.handleNotificationErrorClose}
|
||||||
|
|||||||
@@ -4,24 +4,20 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
|
DataListAction as _DataListAction,
|
||||||
|
DataListCell,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
DataListCell as PFDataListCell,
|
DataListItemRow,
|
||||||
Switch,
|
Switch,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const DataListCell = styled(PFDataListCell)`
|
const DataListAction = styled(_DataListAction)`
|
||||||
display: flex;
|
align-items: center;
|
||||||
justify-content: ${props => (props.righthalf ? 'flex-start' : 'inherit')};
|
display: grid;
|
||||||
padding-bottom: ${props => (props.righthalf ? '16px' : '8px')};
|
grid-gap: 16px;
|
||||||
|
grid-template-columns: repeat(3, max-content);
|
||||||
@media screen and (min-width: 768px) {
|
|
||||||
justify-content: ${props => (props.righthalf ? 'flex-end' : 'inherit')};
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function NotificationListItem(props) {
|
function NotificationListItem(props) {
|
||||||
@@ -51,7 +47,6 @@ function NotificationListItem(props) {
|
|||||||
to={{
|
to={{
|
||||||
pathname: detailUrl,
|
pathname: detailUrl,
|
||||||
}}
|
}}
|
||||||
css="margin-right: 1.5em;"
|
|
||||||
>
|
>
|
||||||
<b id={`items-list-item-${notification.id}`}>
|
<b id={`items-list-item-${notification.id}`}>
|
||||||
{notification.name}
|
{notification.name}
|
||||||
@@ -61,51 +56,47 @@ function NotificationListItem(props) {
|
|||||||
<DataListCell key="type">
|
<DataListCell key="type">
|
||||||
{typeLabels[notification.notification_type]}
|
{typeLabels[notification.notification_type]}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell righthalf="true" key="toggles">
|
|
||||||
<Switch
|
|
||||||
id={`notification-${notification.id}-started-toggle`}
|
|
||||||
label={i18n._(t`Start`)}
|
|
||||||
labelOff={i18n._(t`Start`)}
|
|
||||||
isChecked={startedTurnedOn}
|
|
||||||
isDisabled={!canToggleNotifications}
|
|
||||||
onChange={() =>
|
|
||||||
toggleNotification(
|
|
||||||
notification.id,
|
|
||||||
startedTurnedOn,
|
|
||||||
'started'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
aria-label={i18n._(t`Toggle notification start`)}
|
|
||||||
/>
|
|
||||||
<Switch
|
|
||||||
id={`notification-${notification.id}-success-toggle`}
|
|
||||||
label={i18n._(t`Success`)}
|
|
||||||
labelOff={i18n._(t`Success`)}
|
|
||||||
isChecked={successTurnedOn}
|
|
||||||
isDisabled={!canToggleNotifications}
|
|
||||||
onChange={() =>
|
|
||||||
toggleNotification(
|
|
||||||
notification.id,
|
|
||||||
successTurnedOn,
|
|
||||||
'success'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
aria-label={i18n._(t`Toggle notification success`)}
|
|
||||||
/>
|
|
||||||
<Switch
|
|
||||||
id={`notification-${notification.id}-error-toggle`}
|
|
||||||
label={i18n._(t`Failure`)}
|
|
||||||
labelOff={i18n._(t`Failure`)}
|
|
||||||
isChecked={errorTurnedOn}
|
|
||||||
isDisabled={!canToggleNotifications}
|
|
||||||
onChange={() =>
|
|
||||||
toggleNotification(notification.id, errorTurnedOn, 'error')
|
|
||||||
}
|
|
||||||
aria-label={i18n._(t`Toggle notification failure`)}
|
|
||||||
/>
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={`items-list-item-${notification.id}`}
|
||||||
|
id={`items-list-item-${notification.id}`}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
id={`notification-${notification.id}-started-toggle`}
|
||||||
|
label={i18n._(t`Start`)}
|
||||||
|
labelOff={i18n._(t`Start`)}
|
||||||
|
isChecked={startedTurnedOn}
|
||||||
|
isDisabled={!canToggleNotifications}
|
||||||
|
onChange={() =>
|
||||||
|
toggleNotification(notification.id, startedTurnedOn, 'started')
|
||||||
|
}
|
||||||
|
aria-label={i18n._(t`Toggle notification start`)}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
id={`notification-${notification.id}-success-toggle`}
|
||||||
|
label={i18n._(t`Success`)}
|
||||||
|
labelOff={i18n._(t`Success`)}
|
||||||
|
isChecked={successTurnedOn}
|
||||||
|
isDisabled={!canToggleNotifications}
|
||||||
|
onChange={() =>
|
||||||
|
toggleNotification(notification.id, successTurnedOn, 'success')
|
||||||
|
}
|
||||||
|
aria-label={i18n._(t`Toggle notification success`)}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
id={`notification-${notification.id}-error-toggle`}
|
||||||
|
label={i18n._(t`Failure`)}
|
||||||
|
labelOff={i18n._(t`Failure`)}
|
||||||
|
isChecked={errorTurnedOn}
|
||||||
|
isDisabled={!canToggleNotifications}
|
||||||
|
onChange={() =>
|
||||||
|
toggleNotification(notification.id, errorTurnedOn, 'error')
|
||||||
|
}
|
||||||
|
aria-label={i18n._(t`Toggle notification failure`)}
|
||||||
|
/>
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={
|
dataListCells={
|
||||||
Array [
|
Array [
|
||||||
<ForwardRef>
|
<DataListCell>
|
||||||
<ForwardRef
|
<ForwardRef
|
||||||
to={
|
to={
|
||||||
Object {
|
Object {
|
||||||
@@ -56,41 +56,10 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
|||||||
Foo
|
Foo
|
||||||
</b>
|
</b>
|
||||||
</ForwardRef>
|
</ForwardRef>
|
||||||
</ForwardRef>,
|
</DataListCell>,
|
||||||
<ForwardRef>
|
<DataListCell>
|
||||||
Slack
|
Slack
|
||||||
</ForwardRef>,
|
</DataListCell>,
|
||||||
<ForwardRef
|
|
||||||
righthalf="true"
|
|
||||||
>
|
|
||||||
<Unknown
|
|
||||||
aria-label="Toggle notification start"
|
|
||||||
id="notification-9000-started-toggle"
|
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Start"
|
|
||||||
labelOff="Start"
|
|
||||||
onChange={[Function]}
|
|
||||||
/>
|
|
||||||
<Unknown
|
|
||||||
aria-label="Toggle notification success"
|
|
||||||
id="notification-9000-success-toggle"
|
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Success"
|
|
||||||
labelOff="Success"
|
|
||||||
onChange={[Function]}
|
|
||||||
/>
|
|
||||||
<Unknown
|
|
||||||
aria-label="Toggle notification failure"
|
|
||||||
id="notification-9000-error-toggle"
|
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Failure"
|
|
||||||
labelOff="Failure"
|
|
||||||
onChange={[Function]}
|
|
||||||
/>
|
|
||||||
</ForwardRef>,
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
key=".0"
|
key=".0"
|
||||||
@@ -99,453 +68,324 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
|||||||
<div
|
<div
|
||||||
className="pf-c-data-list__item-content"
|
className="pf-c-data-list__item-content"
|
||||||
>
|
>
|
||||||
<NotificationListItem__DataListCell
|
<DataListCell
|
||||||
key="name"
|
key="name"
|
||||||
>
|
>
|
||||||
<StyledComponent
|
<div
|
||||||
forwardedComponent={
|
className="pf-c-data-list__cell"
|
||||||
Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"attrs": Array [],
|
|
||||||
"componentStyle": ComponentStyle {
|
|
||||||
"componentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"isStatic": false,
|
|
||||||
"lastClassName": "dXsFLF",
|
|
||||||
"rules": Array [
|
|
||||||
"display:flex;justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:",
|
|
||||||
[Function],
|
|
||||||
";@media screen and (min-width:768px){justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:0;}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"displayName": "NotificationListItem__DataListCell",
|
|
||||||
"foldedComponentIds": Array [],
|
|
||||||
"render": [Function],
|
|
||||||
"styledComponentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"target": [Function],
|
|
||||||
"toString": [Function],
|
|
||||||
"warnTooManyClasses": [Function],
|
|
||||||
"withComponent": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
forwardedRef={null}
|
|
||||||
>
|
>
|
||||||
<DataListCell
|
<Link
|
||||||
className="NotificationListItem__DataListCell-w674ng-0 faYgxF"
|
to={
|
||||||
|
Object {
|
||||||
|
"pathname": "/foo",
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div
|
<LinkAnchor
|
||||||
className="pf-c-data-list__cell NotificationListItem__DataListCell-w674ng-0 faYgxF"
|
href="/foo"
|
||||||
|
navigate={[Function]}
|
||||||
>
|
>
|
||||||
<Styled(Link)
|
<a
|
||||||
to={
|
href="/foo"
|
||||||
Object {
|
onClick={[Function]}
|
||||||
"pathname": "/foo",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<StyledComponent
|
<b
|
||||||
forwardedComponent={
|
id="items-list-item-9000"
|
||||||
Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"attrs": Array [],
|
|
||||||
"componentStyle": ComponentStyle {
|
|
||||||
"componentId": "sc-bdVaJa",
|
|
||||||
"isStatic": true,
|
|
||||||
"lastClassName": "eBseNd",
|
|
||||||
"rules": Array [
|
|
||||||
"margin-right: 1.5em;",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"displayName": "Styled(Link)",
|
|
||||||
"foldedComponentIds": Array [],
|
|
||||||
"propTypes": Object {
|
|
||||||
"innerRef": [Function],
|
|
||||||
"onClick": [Function],
|
|
||||||
"replace": [Function],
|
|
||||||
"target": [Function],
|
|
||||||
"to": [Function],
|
|
||||||
},
|
|
||||||
"render": [Function],
|
|
||||||
"styledComponentId": "sc-bdVaJa",
|
|
||||||
"target": Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"displayName": "Link",
|
|
||||||
"propTypes": Object {
|
|
||||||
"innerRef": [Function],
|
|
||||||
"onClick": [Function],
|
|
||||||
"replace": [Function],
|
|
||||||
"target": [Function],
|
|
||||||
"to": [Function],
|
|
||||||
},
|
|
||||||
"render": [Function],
|
|
||||||
},
|
|
||||||
"toString": [Function],
|
|
||||||
"warnTooManyClasses": [Function],
|
|
||||||
"withComponent": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
forwardedRef={null}
|
|
||||||
to={
|
|
||||||
Object {
|
|
||||||
"pathname": "/foo",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Link
|
Foo
|
||||||
className="sc-bdVaJa eBseNd"
|
</b>
|
||||||
to={
|
</a>
|
||||||
Object {
|
</LinkAnchor>
|
||||||
"pathname": "/foo",
|
</Link>
|
||||||
}
|
</div>
|
||||||
}
|
</DataListCell>
|
||||||
>
|
<DataListCell
|
||||||
<LinkAnchor
|
|
||||||
className="sc-bdVaJa eBseNd"
|
|
||||||
href="/foo"
|
|
||||||
navigate={[Function]}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="sc-bdVaJa eBseNd"
|
|
||||||
href="/foo"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<b
|
|
||||||
id="items-list-item-9000"
|
|
||||||
>
|
|
||||||
Foo
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
</LinkAnchor>
|
|
||||||
</Link>
|
|
||||||
</StyledComponent>
|
|
||||||
</Styled(Link)>
|
|
||||||
</div>
|
|
||||||
</DataListCell>
|
|
||||||
</StyledComponent>
|
|
||||||
</NotificationListItem__DataListCell>
|
|
||||||
<NotificationListItem__DataListCell
|
|
||||||
key="type"
|
key="type"
|
||||||
>
|
>
|
||||||
<StyledComponent
|
<div
|
||||||
forwardedComponent={
|
className="pf-c-data-list__cell"
|
||||||
Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"attrs": Array [],
|
|
||||||
"componentStyle": ComponentStyle {
|
|
||||||
"componentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"isStatic": false,
|
|
||||||
"lastClassName": "dXsFLF",
|
|
||||||
"rules": Array [
|
|
||||||
"display:flex;justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:",
|
|
||||||
[Function],
|
|
||||||
";@media screen and (min-width:768px){justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:0;}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"displayName": "NotificationListItem__DataListCell",
|
|
||||||
"foldedComponentIds": Array [],
|
|
||||||
"render": [Function],
|
|
||||||
"styledComponentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"target": [Function],
|
|
||||||
"toString": [Function],
|
|
||||||
"warnTooManyClasses": [Function],
|
|
||||||
"withComponent": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
forwardedRef={null}
|
|
||||||
>
|
>
|
||||||
<DataListCell
|
Slack
|
||||||
className="NotificationListItem__DataListCell-w674ng-0 faYgxF"
|
</div>
|
||||||
>
|
</DataListCell>
|
||||||
<div
|
</div>
|
||||||
className="pf-c-data-list__cell NotificationListItem__DataListCell-w674ng-0 faYgxF"
|
</DataListItemCells>
|
||||||
>
|
<NotificationListItem__DataListAction
|
||||||
Slack
|
aria-label="actions"
|
||||||
</div>
|
aria-labelledby="items-list-item-9000"
|
||||||
</DataListCell>
|
id="items-list-item-9000"
|
||||||
</StyledComponent>
|
key=".1"
|
||||||
</NotificationListItem__DataListCell>
|
rowid="items-list-item-9000"
|
||||||
<NotificationListItem__DataListCell
|
>
|
||||||
key="toggles"
|
<StyledComponent
|
||||||
righthalf="true"
|
aria-label="actions"
|
||||||
|
aria-labelledby="items-list-item-9000"
|
||||||
|
forwardedComponent={
|
||||||
|
Object {
|
||||||
|
"$$typeof": Symbol(react.forward_ref),
|
||||||
|
"attrs": Array [],
|
||||||
|
"componentStyle": ComponentStyle {
|
||||||
|
"componentId": "NotificationListItem__DataListAction-w674ng-0",
|
||||||
|
"isStatic": true,
|
||||||
|
"lastClassName": "hhZchj",
|
||||||
|
"rules": Array [
|
||||||
|
"align-items:center;display:grid;grid-gap:16px;grid-template-columns:repeat(3,max-content);",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"displayName": "NotificationListItem__DataListAction",
|
||||||
|
"foldedComponentIds": Array [],
|
||||||
|
"render": [Function],
|
||||||
|
"styledComponentId": "NotificationListItem__DataListAction-w674ng-0",
|
||||||
|
"target": [Function],
|
||||||
|
"toString": [Function],
|
||||||
|
"warnTooManyClasses": [Function],
|
||||||
|
"withComponent": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forwardedRef={null}
|
||||||
|
id="items-list-item-9000"
|
||||||
|
rowid="items-list-item-9000"
|
||||||
|
>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby="items-list-item-9000"
|
||||||
|
className="NotificationListItem__DataListAction-w674ng-0 hhZchj"
|
||||||
|
id="items-list-item-9000"
|
||||||
|
rowid="items-list-item-9000"
|
||||||
>
|
>
|
||||||
<StyledComponent
|
<div
|
||||||
forwardedComponent={
|
className="pf-c-data-list__item-action NotificationListItem__DataListAction-w674ng-0 hhZchj"
|
||||||
Object {
|
rowid="items-list-item-9000"
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"attrs": Array [],
|
|
||||||
"componentStyle": ComponentStyle {
|
|
||||||
"componentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"isStatic": false,
|
|
||||||
"lastClassName": "dXsFLF",
|
|
||||||
"rules": Array [
|
|
||||||
"display:flex;justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:",
|
|
||||||
[Function],
|
|
||||||
";@media screen and (min-width:768px){justify-content:",
|
|
||||||
[Function],
|
|
||||||
";padding-bottom:0;}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"displayName": "NotificationListItem__DataListCell",
|
|
||||||
"foldedComponentIds": Array [],
|
|
||||||
"render": [Function],
|
|
||||||
"styledComponentId": "NotificationListItem__DataListCell-w674ng-0",
|
|
||||||
"target": [Function],
|
|
||||||
"toString": [Function],
|
|
||||||
"warnTooManyClasses": [Function],
|
|
||||||
"withComponent": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
forwardedRef={null}
|
|
||||||
righthalf="true"
|
|
||||||
>
|
>
|
||||||
<DataListCell
|
<Component
|
||||||
className="NotificationListItem__DataListCell-w674ng-0 dXsFLF"
|
aria-label="Toggle notification start"
|
||||||
righthalf="true"
|
id="notification-9000-started-toggle"
|
||||||
|
isChecked={false}
|
||||||
|
isDisabled={false}
|
||||||
|
label="Start"
|
||||||
|
labelOff="Start"
|
||||||
|
onChange={[Function]}
|
||||||
>
|
>
|
||||||
<div
|
<ComponentWithOuia
|
||||||
className="pf-c-data-list__cell NotificationListItem__DataListCell-w674ng-0 dXsFLF"
|
component={[Function]}
|
||||||
righthalf="true"
|
componentProps={
|
||||||
|
Object {
|
||||||
|
"aria-label": "Toggle notification start",
|
||||||
|
"id": "notification-9000-started-toggle",
|
||||||
|
"isChecked": false,
|
||||||
|
"isDisabled": false,
|
||||||
|
"label": "Start",
|
||||||
|
"labelOff": "Start",
|
||||||
|
"onChange": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consumerContext={null}
|
||||||
>
|
>
|
||||||
<Component
|
<Switch
|
||||||
aria-label="Toggle notification start"
|
aria-label="Toggle notification start"
|
||||||
|
className=""
|
||||||
id="notification-9000-started-toggle"
|
id="notification-9000-started-toggle"
|
||||||
isChecked={false}
|
isChecked={false}
|
||||||
isDisabled={false}
|
isDisabled={false}
|
||||||
label="Start"
|
label="Start"
|
||||||
labelOff="Start"
|
labelOff="Start"
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
>
|
ouiaContext={
|
||||||
<ComponentWithOuia
|
Object {
|
||||||
component={[Function]}
|
"isOuia": false,
|
||||||
componentProps={
|
"ouiaId": null,
|
||||||
Object {
|
|
||||||
"aria-label": "Toggle notification start",
|
|
||||||
"id": "notification-9000-started-toggle",
|
|
||||||
"isChecked": false,
|
|
||||||
"isDisabled": false,
|
|
||||||
"label": "Start",
|
|
||||||
"labelOff": "Start",
|
|
||||||
"onChange": [Function],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
consumerContext={null}
|
}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="pf-c-switch"
|
||||||
|
htmlFor="notification-9000-started-toggle"
|
||||||
>
|
>
|
||||||
<Switch
|
<input
|
||||||
aria-label="Toggle notification start"
|
aria-label="Toggle notification start"
|
||||||
className=""
|
aria-labelledby={null}
|
||||||
|
checked={false}
|
||||||
|
className="pf-c-switch__input"
|
||||||
|
disabled={false}
|
||||||
id="notification-9000-started-toggle"
|
id="notification-9000-started-toggle"
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Start"
|
|
||||||
labelOff="Start"
|
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
ouiaContext={
|
type="checkbox"
|
||||||
Object {
|
/>
|
||||||
"isOuia": false,
|
<span
|
||||||
"ouiaId": null,
|
className="pf-c-switch__toggle"
|
||||||
}
|
/>
|
||||||
}
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="pf-c-switch__label pf-m-on"
|
||||||
|
id={null}
|
||||||
>
|
>
|
||||||
<label
|
Start
|
||||||
className="pf-c-switch"
|
</span>
|
||||||
htmlFor="notification-9000-started-toggle"
|
<span
|
||||||
>
|
aria-hidden="true"
|
||||||
<input
|
className="pf-c-switch__label pf-m-off"
|
||||||
aria-label="Toggle notification start"
|
id={null}
|
||||||
aria-labelledby={null}
|
>
|
||||||
checked={false}
|
Start
|
||||||
className="pf-c-switch__input"
|
</span>
|
||||||
disabled={false}
|
</label>
|
||||||
id="notification-9000-started-toggle"
|
</Switch>
|
||||||
onChange={[Function]}
|
</ComponentWithOuia>
|
||||||
type="checkbox"
|
</Component>
|
||||||
/>
|
<Component
|
||||||
<span
|
aria-label="Toggle notification success"
|
||||||
className="pf-c-switch__toggle"
|
id="notification-9000-success-toggle"
|
||||||
/>
|
isChecked={false}
|
||||||
<span
|
isDisabled={false}
|
||||||
aria-hidden="true"
|
label="Success"
|
||||||
className="pf-c-switch__label pf-m-on"
|
labelOff="Success"
|
||||||
id={null}
|
onChange={[Function]}
|
||||||
>
|
>
|
||||||
Start
|
<ComponentWithOuia
|
||||||
</span>
|
component={[Function]}
|
||||||
<span
|
componentProps={
|
||||||
aria-hidden="true"
|
Object {
|
||||||
className="pf-c-switch__label pf-m-off"
|
"aria-label": "Toggle notification success",
|
||||||
id={null}
|
"id": "notification-9000-success-toggle",
|
||||||
>
|
"isChecked": false,
|
||||||
Start
|
"isDisabled": false,
|
||||||
</span>
|
"label": "Success",
|
||||||
</label>
|
"labelOff": "Success",
|
||||||
</Switch>
|
"onChange": [Function],
|
||||||
</ComponentWithOuia>
|
}
|
||||||
</Component>
|
}
|
||||||
<Component
|
consumerContext={null}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
aria-label="Toggle notification success"
|
aria-label="Toggle notification success"
|
||||||
|
className=""
|
||||||
id="notification-9000-success-toggle"
|
id="notification-9000-success-toggle"
|
||||||
isChecked={false}
|
isChecked={false}
|
||||||
isDisabled={false}
|
isDisabled={false}
|
||||||
label="Success"
|
label="Success"
|
||||||
labelOff="Success"
|
labelOff="Success"
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
>
|
ouiaContext={
|
||||||
<ComponentWithOuia
|
Object {
|
||||||
component={[Function]}
|
"isOuia": false,
|
||||||
componentProps={
|
"ouiaId": null,
|
||||||
Object {
|
|
||||||
"aria-label": "Toggle notification success",
|
|
||||||
"id": "notification-9000-success-toggle",
|
|
||||||
"isChecked": false,
|
|
||||||
"isDisabled": false,
|
|
||||||
"label": "Success",
|
|
||||||
"labelOff": "Success",
|
|
||||||
"onChange": [Function],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
consumerContext={null}
|
}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="pf-c-switch"
|
||||||
|
htmlFor="notification-9000-success-toggle"
|
||||||
>
|
>
|
||||||
<Switch
|
<input
|
||||||
aria-label="Toggle notification success"
|
aria-label="Toggle notification success"
|
||||||
className=""
|
aria-labelledby={null}
|
||||||
|
checked={false}
|
||||||
|
className="pf-c-switch__input"
|
||||||
|
disabled={false}
|
||||||
id="notification-9000-success-toggle"
|
id="notification-9000-success-toggle"
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Success"
|
|
||||||
labelOff="Success"
|
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
ouiaContext={
|
type="checkbox"
|
||||||
Object {
|
/>
|
||||||
"isOuia": false,
|
<span
|
||||||
"ouiaId": null,
|
className="pf-c-switch__toggle"
|
||||||
}
|
/>
|
||||||
}
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="pf-c-switch__label pf-m-on"
|
||||||
|
id={null}
|
||||||
>
|
>
|
||||||
<label
|
Success
|
||||||
className="pf-c-switch"
|
</span>
|
||||||
htmlFor="notification-9000-success-toggle"
|
<span
|
||||||
>
|
aria-hidden="true"
|
||||||
<input
|
className="pf-c-switch__label pf-m-off"
|
||||||
aria-label="Toggle notification success"
|
id={null}
|
||||||
aria-labelledby={null}
|
>
|
||||||
checked={false}
|
Success
|
||||||
className="pf-c-switch__input"
|
</span>
|
||||||
disabled={false}
|
</label>
|
||||||
id="notification-9000-success-toggle"
|
</Switch>
|
||||||
onChange={[Function]}
|
</ComponentWithOuia>
|
||||||
type="checkbox"
|
</Component>
|
||||||
/>
|
<Component
|
||||||
<span
|
aria-label="Toggle notification failure"
|
||||||
className="pf-c-switch__toggle"
|
id="notification-9000-error-toggle"
|
||||||
/>
|
isChecked={false}
|
||||||
<span
|
isDisabled={false}
|
||||||
aria-hidden="true"
|
label="Failure"
|
||||||
className="pf-c-switch__label pf-m-on"
|
labelOff="Failure"
|
||||||
id={null}
|
onChange={[Function]}
|
||||||
>
|
>
|
||||||
Success
|
<ComponentWithOuia
|
||||||
</span>
|
component={[Function]}
|
||||||
<span
|
componentProps={
|
||||||
aria-hidden="true"
|
Object {
|
||||||
className="pf-c-switch__label pf-m-off"
|
"aria-label": "Toggle notification failure",
|
||||||
id={null}
|
"id": "notification-9000-error-toggle",
|
||||||
>
|
"isChecked": false,
|
||||||
Success
|
"isDisabled": false,
|
||||||
</span>
|
"label": "Failure",
|
||||||
</label>
|
"labelOff": "Failure",
|
||||||
</Switch>
|
"onChange": [Function],
|
||||||
</ComponentWithOuia>
|
}
|
||||||
</Component>
|
}
|
||||||
<Component
|
consumerContext={null}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
aria-label="Toggle notification failure"
|
aria-label="Toggle notification failure"
|
||||||
|
className=""
|
||||||
id="notification-9000-error-toggle"
|
id="notification-9000-error-toggle"
|
||||||
isChecked={false}
|
isChecked={false}
|
||||||
isDisabled={false}
|
isDisabled={false}
|
||||||
label="Failure"
|
label="Failure"
|
||||||
labelOff="Failure"
|
labelOff="Failure"
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
>
|
ouiaContext={
|
||||||
<ComponentWithOuia
|
Object {
|
||||||
component={[Function]}
|
"isOuia": false,
|
||||||
componentProps={
|
"ouiaId": null,
|
||||||
Object {
|
|
||||||
"aria-label": "Toggle notification failure",
|
|
||||||
"id": "notification-9000-error-toggle",
|
|
||||||
"isChecked": false,
|
|
||||||
"isDisabled": false,
|
|
||||||
"label": "Failure",
|
|
||||||
"labelOff": "Failure",
|
|
||||||
"onChange": [Function],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
consumerContext={null}
|
}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="pf-c-switch"
|
||||||
|
htmlFor="notification-9000-error-toggle"
|
||||||
>
|
>
|
||||||
<Switch
|
<input
|
||||||
aria-label="Toggle notification failure"
|
aria-label="Toggle notification failure"
|
||||||
className=""
|
aria-labelledby={null}
|
||||||
|
checked={false}
|
||||||
|
className="pf-c-switch__input"
|
||||||
|
disabled={false}
|
||||||
id="notification-9000-error-toggle"
|
id="notification-9000-error-toggle"
|
||||||
isChecked={false}
|
|
||||||
isDisabled={false}
|
|
||||||
label="Failure"
|
|
||||||
labelOff="Failure"
|
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
ouiaContext={
|
type="checkbox"
|
||||||
Object {
|
/>
|
||||||
"isOuia": false,
|
<span
|
||||||
"ouiaId": null,
|
className="pf-c-switch__toggle"
|
||||||
}
|
/>
|
||||||
}
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="pf-c-switch__label pf-m-on"
|
||||||
|
id={null}
|
||||||
>
|
>
|
||||||
<label
|
Failure
|
||||||
className="pf-c-switch"
|
</span>
|
||||||
htmlFor="notification-9000-error-toggle"
|
<span
|
||||||
>
|
aria-hidden="true"
|
||||||
<input
|
className="pf-c-switch__label pf-m-off"
|
||||||
aria-label="Toggle notification failure"
|
id={null}
|
||||||
aria-labelledby={null}
|
>
|
||||||
checked={false}
|
Failure
|
||||||
className="pf-c-switch__input"
|
</span>
|
||||||
disabled={false}
|
</label>
|
||||||
id="notification-9000-error-toggle"
|
</Switch>
|
||||||
onChange={[Function]}
|
</ComponentWithOuia>
|
||||||
type="checkbox"
|
</Component>
|
||||||
/>
|
</div>
|
||||||
<span
|
</DataListAction>
|
||||||
className="pf-c-switch__toggle"
|
</StyledComponent>
|
||||||
/>
|
</NotificationListItem__DataListAction>
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className="pf-c-switch__label pf-m-on"
|
|
||||||
id={null}
|
|
||||||
>
|
|
||||||
Failure
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className="pf-c-switch__label pf-m-off"
|
|
||||||
id={null}
|
|
||||||
>
|
|
||||||
Failure
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</Switch>
|
|
||||||
</ComponentWithOuia>
|
|
||||||
</Component>
|
|
||||||
</div>
|
|
||||||
</DataListCell>
|
|
||||||
</StyledComponent>
|
|
||||||
</NotificationListItem__DataListCell>
|
|
||||||
</div>
|
|
||||||
</DataListItemCells>
|
|
||||||
</div>
|
</div>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ class ToolbarDeleteButton extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { itemsToDelete, pluralizedItemName, i18n } = this.props;
|
const { itemsToDelete, pluralizedItemName, i18n } = this.props;
|
||||||
const { isModalOpen } = this.state;
|
const { isModalOpen } = this.state;
|
||||||
|
const modalTitle = i18n._(t`Delete ${pluralizedItemName}?`);
|
||||||
|
|
||||||
const isDisabled =
|
const isDisabled =
|
||||||
itemsToDelete.length === 0 || itemsToDelete.some(cannotDelete);
|
itemsToDelete.length === 0 || itemsToDelete.some(cannotDelete);
|
||||||
@@ -161,7 +162,7 @@ class ToolbarDeleteButton extends React.Component {
|
|||||||
{isModalOpen && (
|
{isModalOpen && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="danger"
|
||||||
title={pluralizedItemName}
|
title={modalTitle}
|
||||||
isOpen={isModalOpen}
|
isOpen={isModalOpen}
|
||||||
onClose={this.handleCancelDelete}
|
onClose={this.handleCancelDelete}
|
||||||
actions={[
|
actions={[
|
||||||
@@ -183,15 +184,13 @@ class ToolbarDeleteButton extends React.Component {
|
|||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{i18n._(t`Are you sure you want to delete:`)}
|
<div>{i18n._(t`This action will delete the following:`)}</div>
|
||||||
<br />
|
|
||||||
{itemsToDelete.map(item => (
|
{itemsToDelete.map(item => (
|
||||||
<span key={item.id}>
|
<span key={item.id}>
|
||||||
<strong>{item.name || item.username}</strong>
|
<strong>{item.name || item.username}</strong>
|
||||||
<br />
|
<br />
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
<br />
|
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ class ResourceAccessList extends React.Component {
|
|||||||
)}
|
)}
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={hasDeletionError}
|
isOpen={hasDeletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
aria-describedby="pf-modal-0"
|
aria-describedby="pf-modal-0"
|
||||||
aria-label="Remove {0} Access"
|
aria-label="Remove {0} Access"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
class="pf-c-modal-box awx-c-modal at-c-alertModal at-c-alertModal--danger pf-m-lg"
|
class="pf-c-modal-box pf-m-sm"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -96,13 +96,34 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<h1
|
<div
|
||||||
class="pf-c-title pf-m-2xl"
|
class="pf-c-title"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
Remove {0} Access
|
class="AlertModal__Header-sc-9waqvl-0 dYqVFx"
|
||||||
|
>
|
||||||
</h1>
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="sc-bdVaJa bkDjEn"
|
||||||
|
fill="currentColor"
|
||||||
|
height="2em"
|
||||||
|
role="img"
|
||||||
|
style="vertical-align: -0.25em;"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="2em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
||||||
|
transform=""
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h1
|
||||||
|
class="pf-c-title pf-m-2xl"
|
||||||
|
>
|
||||||
|
Remove {0} Access
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="pf-c-modal-box__body"
|
class="pf-c-modal-box__body"
|
||||||
id="pf-modal-0"
|
id="pf-modal-0"
|
||||||
@@ -111,24 +132,9 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
If you only want to remove access for this particular user, please remove them from the team.
|
If you only want to remove access for this particular user, please remove them from the team.
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
class="at-c-alertModal__icon"
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
role="img"
|
|
||||||
style="vertical-align: -0.125em;"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
|
||||||
transform=""
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="pf-c-modal-box__footer"
|
class="pf-c-modal-box__footer pf-m-align-left"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Confirm delete"
|
aria-label="Confirm delete"
|
||||||
@@ -151,12 +157,24 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
</body>
|
</body>
|
||||||
}
|
}
|
||||||
ariaDescribedById=""
|
ariaDescribedById=""
|
||||||
className="awx-c-modal at-c-alertModal at-c-alertModal--danger"
|
className=""
|
||||||
|
header={
|
||||||
|
<ForwardRef>
|
||||||
|
<ForwardRef
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
<Title
|
||||||
|
size="2xl"
|
||||||
|
>
|
||||||
|
Remove {0} Access
|
||||||
|
</Title>
|
||||||
|
</ForwardRef>
|
||||||
|
}
|
||||||
hideTitle={false}
|
hideTitle={false}
|
||||||
isFooterLeftAligned={false}
|
isFooterLeftAligned={true}
|
||||||
isLarge={true}
|
isLarge={false}
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
isSmall={false}
|
isSmall={true}
|
||||||
onClose={[Function]}
|
onClose={[Function]}
|
||||||
showClose={true}
|
showClose={true}
|
||||||
title="Remove {0} Access"
|
title="Remove {0} Access"
|
||||||
@@ -174,7 +192,7 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
aria-describedby="pf-modal-0"
|
aria-describedby="pf-modal-0"
|
||||||
aria-label="Remove {0} Access"
|
aria-label="Remove {0} Access"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
class="pf-c-modal-box awx-c-modal at-c-alertModal at-c-alertModal--danger pf-m-lg"
|
class="pf-c-modal-box pf-m-sm"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -197,13 +215,34 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<h1
|
<div
|
||||||
class="pf-c-title pf-m-2xl"
|
class="pf-c-title"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
Remove {0} Access
|
class="AlertModal__Header-sc-9waqvl-0 dYqVFx"
|
||||||
|
>
|
||||||
</h1>
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="sc-bdVaJa bkDjEn"
|
||||||
|
fill="currentColor"
|
||||||
|
height="2em"
|
||||||
|
role="img"
|
||||||
|
style="vertical-align: -0.25em;"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="2em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
||||||
|
transform=""
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h1
|
||||||
|
class="pf-c-title pf-m-2xl"
|
||||||
|
>
|
||||||
|
Remove {0} Access
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="pf-c-modal-box__body"
|
class="pf-c-modal-box__body"
|
||||||
id="pf-modal-0"
|
id="pf-modal-0"
|
||||||
@@ -212,24 +251,9 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
If you only want to remove access for this particular user, please remove them from the team.
|
If you only want to remove access for this particular user, please remove them from the team.
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
class="at-c-alertModal__icon"
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
role="img"
|
|
||||||
style="vertical-align: -0.125em;"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
|
||||||
transform=""
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="pf-c-modal-box__footer"
|
class="pf-c-modal-box__footer pf-m-align-left"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Confirm delete"
|
aria-label="Confirm delete"
|
||||||
@@ -270,13 +294,25 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
ariaDescribedById=""
|
ariaDescribedById=""
|
||||||
className="awx-c-modal at-c-alertModal at-c-alertModal--danger"
|
className=""
|
||||||
|
header={
|
||||||
|
<ForwardRef>
|
||||||
|
<ForwardRef
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
<Title
|
||||||
|
size="2xl"
|
||||||
|
>
|
||||||
|
Remove {0} Access
|
||||||
|
</Title>
|
||||||
|
</ForwardRef>
|
||||||
|
}
|
||||||
hideTitle={false}
|
hideTitle={false}
|
||||||
id="pf-modal-0"
|
id="pf-modal-0"
|
||||||
isFooterLeftAligned={false}
|
isFooterLeftAligned={true}
|
||||||
isLarge={true}
|
isLarge={false}
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
isSmall={false}
|
isSmall={true}
|
||||||
onClose={[Function]}
|
onClose={[Function]}
|
||||||
showClose={true}
|
showClose={true}
|
||||||
title="Remove {0} Access"
|
title="Remove {0} Access"
|
||||||
@@ -301,10 +337,10 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
className="pf-l-bullseye"
|
className="pf-l-bullseye"
|
||||||
>
|
>
|
||||||
<ModalBox
|
<ModalBox
|
||||||
className="awx-c-modal at-c-alertModal at-c-alertModal--danger"
|
className=""
|
||||||
id="pf-modal-0"
|
id="pf-modal-0"
|
||||||
isLarge={true}
|
isLarge={false}
|
||||||
isSmall={false}
|
isSmall={true}
|
||||||
style={Object {}}
|
style={Object {}}
|
||||||
title="Remove {0} Access"
|
title="Remove {0} Access"
|
||||||
>
|
>
|
||||||
@@ -312,7 +348,7 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
aria-describedby="pf-modal-0"
|
aria-describedby="pf-modal-0"
|
||||||
aria-label="Remove {0} Access"
|
aria-label="Remove {0} Access"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
className="pf-c-modal-box awx-c-modal at-c-alertModal at-c-alertModal--danger pf-m-lg"
|
className="pf-c-modal-box pf-m-sm"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
style={Object {}}
|
style={Object {}}
|
||||||
>
|
>
|
||||||
@@ -395,23 +431,110 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
</ComponentWithOuia>
|
</ComponentWithOuia>
|
||||||
</Component>
|
</Component>
|
||||||
</ModalBoxCloseButton>
|
</ModalBoxCloseButton>
|
||||||
<ModalBoxHeader
|
<div
|
||||||
hideTitle={false}
|
className="pf-c-title"
|
||||||
>
|
>
|
||||||
<Title
|
<AlertModal__Header>
|
||||||
className=""
|
<StyledComponent
|
||||||
headingLevel="h1"
|
forwardedComponent={
|
||||||
size="2xl"
|
Object {
|
||||||
>
|
"$$typeof": Symbol(react.forward_ref),
|
||||||
<h1
|
"attrs": Array [],
|
||||||
className="pf-c-title pf-m-2xl"
|
"componentStyle": ComponentStyle {
|
||||||
|
"componentId": "AlertModal__Header-sc-9waqvl-0",
|
||||||
|
"isStatic": true,
|
||||||
|
"lastClassName": "dYqVFx",
|
||||||
|
"rules": Array [
|
||||||
|
"display:flex;svg{margin-right:16px;}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"displayName": "AlertModal__Header",
|
||||||
|
"foldedComponentIds": Array [],
|
||||||
|
"render": [Function],
|
||||||
|
"styledComponentId": "AlertModal__Header-sc-9waqvl-0",
|
||||||
|
"target": "div",
|
||||||
|
"toString": [Function],
|
||||||
|
"warnTooManyClasses": [Function],
|
||||||
|
"withComponent": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forwardedRef={null}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
Remove {0} Access
|
className="AlertModal__Header-sc-9waqvl-0 dYqVFx"
|
||||||
|
>
|
||||||
</h1>
|
<Styled(ExclamationCircleIcon)
|
||||||
</Title>
|
size="lg"
|
||||||
</ModalBoxHeader>
|
>
|
||||||
|
<StyledComponent
|
||||||
|
forwardedComponent={
|
||||||
|
Object {
|
||||||
|
"$$typeof": Symbol(react.forward_ref),
|
||||||
|
"attrs": Array [],
|
||||||
|
"componentStyle": ComponentStyle {
|
||||||
|
"componentId": "sc-bdVaJa",
|
||||||
|
"isStatic": true,
|
||||||
|
"lastClassName": "bkDjEn",
|
||||||
|
"rules": Array [
|
||||||
|
"color: #c9190b",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"displayName": "Styled(ExclamationCircleIcon)",
|
||||||
|
"foldedComponentIds": Array [],
|
||||||
|
"render": [Function],
|
||||||
|
"styledComponentId": "sc-bdVaJa",
|
||||||
|
"target": [Function],
|
||||||
|
"toString": [Function],
|
||||||
|
"warnTooManyClasses": [Function],
|
||||||
|
"withComponent": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forwardedRef={null}
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
|
<ExclamationCircleIcon
|
||||||
|
className="sc-bdVaJa bkDjEn"
|
||||||
|
color="currentColor"
|
||||||
|
noVerticalAlign={false}
|
||||||
|
size="lg"
|
||||||
|
title={null}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden={true}
|
||||||
|
aria-labelledby={null}
|
||||||
|
className="sc-bdVaJa bkDjEn"
|
||||||
|
fill="currentColor"
|
||||||
|
height="2em"
|
||||||
|
role="img"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"verticalAlign": "-0.25em",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="2em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
||||||
|
transform=""
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</ExclamationCircleIcon>
|
||||||
|
</StyledComponent>
|
||||||
|
</Styled(ExclamationCircleIcon)>
|
||||||
|
<Title
|
||||||
|
size="2xl"
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
className="pf-c-title pf-m-2xl"
|
||||||
|
>
|
||||||
|
Remove {0} Access
|
||||||
|
</h1>
|
||||||
|
</Title>
|
||||||
|
</div>
|
||||||
|
</StyledComponent>
|
||||||
|
</AlertModal__Header>
|
||||||
|
</div>
|
||||||
<ModalBoxBody
|
<ModalBoxBody
|
||||||
id="pf-modal-0"
|
id="pf-modal-0"
|
||||||
>
|
>
|
||||||
@@ -423,41 +546,13 @@ exports[`<DeleteRoleConfirmationModal /> should render initially 1`] = `
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
If you only want to remove access for this particular user, please remove them from the team.
|
If you only want to remove access for this particular user, please remove them from the team.
|
||||||
<ExclamationCircleIcon
|
|
||||||
className="at-c-alertModal__icon"
|
|
||||||
color="currentColor"
|
|
||||||
noVerticalAlign={false}
|
|
||||||
size="sm"
|
|
||||||
title={null}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
aria-labelledby={null}
|
|
||||||
className="at-c-alertModal__icon"
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
role="img"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"verticalAlign": "-0.125em",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
|
|
||||||
transform=""
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</ExclamationCircleIcon>
|
|
||||||
</div>
|
</div>
|
||||||
</ModalBoxBody>
|
</ModalBoxBody>
|
||||||
<ModalBoxFooter
|
<ModalBoxFooter
|
||||||
isLeftAligned={false}
|
isLeftAligned={true}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="pf-c-modal-box__footer"
|
className="pf-c-modal-box__footer pf-m-align-left"
|
||||||
>
|
>
|
||||||
<Component
|
<Component
|
||||||
aria-label="Confirm delete"
|
aria-label="Confirm delete"
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
SplitItem,
|
SplitItem,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import VerticalSeparator from '../VerticalSeparator';
|
|
||||||
|
|
||||||
const Split = styled(PFSplit)`
|
const Split = styled(PFSplit)`
|
||||||
margin: 20px 0px;
|
margin: 20px 0px;
|
||||||
@@ -16,6 +15,7 @@ const Split = styled(PFSplit)`
|
|||||||
|
|
||||||
const SplitLabelItem = styled(SplitItem)`
|
const SplitLabelItem = styled(SplitItem)`
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
margin-right: 32px;
|
||||||
word-break: initial;
|
word-break: initial;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -41,7 +41,6 @@ class SelectedList extends Component {
|
|||||||
return (
|
return (
|
||||||
<Split>
|
<Split>
|
||||||
<SplitLabelItem>{label}</SplitLabelItem>
|
<SplitLabelItem>{label}</SplitLabelItem>
|
||||||
<VerticalSeparator />
|
|
||||||
<SplitItem>
|
<SplitItem>
|
||||||
<ChipGroup numChips={5}>
|
<ChipGroup numChips={5}>
|
||||||
{selected.map(item =>
|
{selected.map(item =>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
|||||||
import { arrayOf, object } from 'prop-types';
|
import { arrayOf, object } from 'prop-types';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { Link as _Link } from 'react-router-dom';
|
import { Link as _Link } from 'react-router-dom';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import { Tooltip } from '@patternfly/react-core';
|
import { Tooltip } from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -13,6 +13,10 @@ import { JOB_TYPE_URL_SEGMENTS } from '@constants';
|
|||||||
const Link = styled(props => <_Link {...props} />)`
|
const Link = styled(props => <_Link {...props} />)`
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
display: inline-flex;
|
||||||
|
`;
|
||||||
/* eslint-enable react/jsx-pascal-case */
|
/* eslint-enable react/jsx-pascal-case */
|
||||||
|
|
||||||
const Sparkline = ({ i18n, jobs }) => {
|
const Sparkline = ({ i18n, jobs }) => {
|
||||||
@@ -32,13 +36,15 @@ const Sparkline = ({ i18n, jobs }) => {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
return jobs.map(job => (
|
const statusIcons = jobs.map(job => (
|
||||||
<Tooltip position="top" content={generateTooltip(job)} key={job.id}>
|
<Tooltip position="top" content={generateTooltip(job)} key={job.id}>
|
||||||
<Link to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}>
|
<Link to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}>
|
||||||
<StatusIcon status={job.status} />
|
<StatusIcon status={job.status} />
|
||||||
</Link>
|
</Link>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
return <Wrapper>{statusIcons}</Wrapper>;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sparkline.propTypes = {
|
Sparkline.propTypes = {
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
export { default as Sparkline } from './Sparkline';
|
export { default } from './Sparkline';
|
||||||
export { default as StatusIcon } from './StatusIcon';
|
|
||||||
|
|||||||
@@ -12,8 +12,12 @@ const Pulse = keyframes`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
width: 14px;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
|
margin: 5px 0;
|
||||||
|
width: 14px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const WhiteTop = styled.div`
|
const WhiteTop = styled.div`
|
||||||
1
awx/ui_next/src/components/StatusIcon/index.js
Normal file
1
awx/ui_next/src/components/StatusIcon/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { default } from './StatusIcon';
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Separator = styled.span`
|
|
||||||
display: inline-block;
|
|
||||||
width: 1px;
|
|
||||||
height: 30px;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
background-color: #d7d7d7;
|
|
||||||
vertical-align: middle;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const VerticalSeparator = () => (
|
|
||||||
<div>
|
|
||||||
<Separator />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default VerticalSeparator;
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { mount } from 'enzyme';
|
|
||||||
|
|
||||||
import VerticalSeparator from './VerticalSeparator';
|
|
||||||
|
|
||||||
describe('VerticalSeparator', () => {
|
|
||||||
test('renders the expected content', () => {
|
|
||||||
const wrapper = mount(<VerticalSeparator />);
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default } from './VerticalSeparator';
|
|
||||||
@@ -4,7 +4,7 @@ import WorkflowActionTooltipItem from './WorkflowActionTooltipItem';
|
|||||||
|
|
||||||
describe('WorkflowActionTooltipItem', () => {
|
describe('WorkflowActionTooltipItem', () => {
|
||||||
test('successfully mounts', () => {
|
test('successfully mounts', () => {
|
||||||
const wrapper = mount(<WorkflowActionTooltipItem />);
|
const wrapper = mount(<WorkflowActionTooltipItem id="node" />);
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(wrapper).toHaveLength(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { I18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
import '@patternfly/react-core/dist/styles/base.css';
|
import '@patternfly/react-core/dist/styles/base.css';
|
||||||
import './app.scss';
|
|
||||||
|
|
||||||
import { isAuthenticated } from '@util/auth';
|
import { isAuthenticated } from '@util/auth';
|
||||||
import Background from '@components/Background';
|
import Background from '@components/Background';
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ function CredentialDetail({ i18n, credential }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -125,9 +125,9 @@ function CredentialList({ i18n }) {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName={i18n._(t`Credentials`)}
|
pluralizedItemName={i18n._(t`Credentials`)}
|
||||||
/>,
|
/>,
|
||||||
canAdd && (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo="/credentials/add" />
|
? [<ToolbarAddButton key="add" linkTo="/credentials/add" />]
|
||||||
),
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -135,7 +135,7 @@ function CredentialList({ i18n }) {
|
|||||||
</Card>
|
</Card>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={clearDeletionError}
|
onClose={clearDeletionError}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -54,44 +54,44 @@ describe('<CredentialList />', () => {
|
|||||||
|
|
||||||
test('should check and uncheck the row item', async () => {
|
test('should check and uncheck the row item', async () => {
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-credential-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-credential-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find('PFDataListCheck[id="select-credential-1"]')
|
.find('DataListCheck[id="select-credential-1"]')
|
||||||
.invoke('onChange')(true);
|
.invoke('onChange')(true);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-credential-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-credential-1"]').props().checked
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find('PFDataListCheck[id="select-credential-1"]')
|
.find('DataListCheck[id="select-credential-1"]')
|
||||||
.invoke('onChange')(false);
|
.invoke('onChange')(false);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-credential-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-credential-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should check all row items when select all is checked', async () => {
|
test('should check all row items when select all is checked', async () => {
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(true);
|
expect(el.props().checked).toBe(true);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -102,7 +102,7 @@ describe('<CredentialList />', () => {
|
|||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find('PFDataListCheck[id="select-credential-3"]')
|
.find('DataListCheck[id="select-credential-3"]')
|
||||||
.invoke('onChange')();
|
.invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
@@ -119,7 +119,7 @@ describe('<CredentialList />', () => {
|
|||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find('PFDataListCheck[id="select-credential-2"]')
|
.find('DataListCheck[id="select-credential-2"]')
|
||||||
.invoke('onChange')();
|
.invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
|
|||||||
@@ -5,25 +5,18 @@ import { t } from '@lingui/macro';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
DataListItemRow,
|
||||||
DataListItemCells as _DataListItemCells,
|
DataListItemCells,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { Credential } from '@types';
|
import { Credential } from '@types';
|
||||||
|
|
||||||
const DataListItemCells = styled(_DataListItemCells)`
|
|
||||||
${DataListCell}:first-child {
|
|
||||||
flex-grow: 2;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
function CredentialListItem({
|
function CredentialListItem({
|
||||||
credential,
|
credential,
|
||||||
detailUrl,
|
detailUrl,
|
||||||
@@ -50,7 +43,6 @@ function CredentialListItem({
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="name">
|
<DataListCell key="name">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{credential.name}</b>
|
<b>{credential.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -58,21 +50,25 @@ function CredentialListItem({
|
|||||||
<DataListCell key="type">
|
<DataListCell key="type">
|
||||||
{credential.summary_fields.credential_type.name}
|
{credential.summary_fields.credential_type.name}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{canEdit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Credential`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/credentials/${credential.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{canEdit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Credential`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/credentials/${credential.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import AlertModal from '@components/AlertModal';
|
|||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
|
import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
|
||||||
import { VariablesDetail } from '@components/CodeMirrorInput';
|
import { VariablesDetail } from '@components/CodeMirrorInput';
|
||||||
import { Sparkline } from '@components/Sparkline';
|
import Sparkline from '@components/Sparkline';
|
||||||
import DeleteButton from '@components/DeleteButton';
|
import DeleteButton from '@components/DeleteButton';
|
||||||
import { HostsAPI } from '@api';
|
import { HostsAPI } from '@api';
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ function HostDetail({ host, i18n, onUpdateHost }) {
|
|||||||
if (toggleError && !toggleLoading) {
|
if (toggleError && !toggleLoading) {
|
||||||
return (
|
return (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
isOpen={toggleError && !toggleLoading}
|
isOpen={toggleError && !toggleLoading}
|
||||||
onClose={() => setToggleError(false)}
|
onClose={() => setToggleError(false)}
|
||||||
@@ -83,7 +83,7 @@ function HostDetail({ host, i18n, onUpdateHost }) {
|
|||||||
return (
|
return (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(false)}
|
onClose={() => setDeletionError(false)}
|
||||||
>
|
>
|
||||||
@@ -107,7 +107,6 @@ function HostDetail({ host, i18n, onUpdateHost }) {
|
|||||||
<DetailList gutter="sm">
|
<DetailList gutter="sm">
|
||||||
<Detail label={i18n._(t`Name`)} value={name} />
|
<Detail label={i18n._(t`Name`)} value={name} />
|
||||||
<Detail
|
<Detail
|
||||||
css="display: flex; flex: 1;"
|
|
||||||
value={<Sparkline jobs={recentPlaybookJobs} />}
|
value={<Sparkline jobs={recentPlaybookJobs} />}
|
||||||
label={i18n._(t`Activity`)}
|
label={i18n._(t`Activity`)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -224,9 +224,14 @@ class HostsList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName={i18n._(t`Hosts`)}
|
pluralizedItemName={i18n._(t`Hosts`)}
|
||||||
/>,
|
/>,
|
||||||
canAdd ? (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} />
|
? [
|
||||||
) : null,
|
<ToolbarAddButton
|
||||||
|
key="add"
|
||||||
|
linkTo={`${match.url}/add`}
|
||||||
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -250,7 +255,7 @@ class HostsList extends Component {
|
|||||||
</Card>
|
</Card>
|
||||||
{toggleError && !toggleLoading && (
|
{toggleError && !toggleLoading && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
isOpen={toggleError && !toggleLoading}
|
isOpen={toggleError && !toggleLoading}
|
||||||
onClose={this.handleHostToggleErrorClose}
|
onClose={this.handleHostToggleErrorClose}
|
||||||
@@ -262,7 +267,7 @@ class HostsList extends Component {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction as _DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
DataListItemRow,
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
@@ -13,11 +16,16 @@ import {
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
import Sparkline from '@components/Sparkline';
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import { Sparkline } from '@components/Sparkline';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { Host } from '@types';
|
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 {
|
class HostListItem extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -56,7 +64,6 @@ class HostListItem extends React.Component {
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="name">
|
<DataListCell key="name">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{host.name}</b>
|
<b>{host.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -67,9 +74,7 @@ class HostListItem extends React.Component {
|
|||||||
<DataListCell key="inventory">
|
<DataListCell key="inventory">
|
||||||
{host.summary_fields.inventory && (
|
{host.summary_fields.inventory && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<b style={{ marginRight: '20px' }}>
|
<b css="margin-right: 24px">{i18n._(t`Inventory`)}</b>
|
||||||
{i18n._(t`Inventory`)}
|
|
||||||
</b>
|
|
||||||
<Link
|
<Link
|
||||||
to={`/inventories/${
|
to={`/inventories/${
|
||||||
host.summary_fields.inventory.kind === 'smart'
|
host.summary_fields.inventory.kind === 'smart'
|
||||||
@@ -82,43 +87,44 @@ class HostListItem extends React.Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="enable" alignRight isFilled={false}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(
|
|
||||||
t`Indicates if a host is available and should be included in running jobs. For hosts that are part of an external inventory, this may be reset by the inventory sync process.`
|
|
||||||
)}
|
|
||||||
position="top"
|
|
||||||
>
|
|
||||||
<Switch
|
|
||||||
css="display: inline-flex;"
|
|
||||||
id={`host-${host.id}-toggle`}
|
|
||||||
label={i18n._(t`On`)}
|
|
||||||
labelOff={i18n._(t`Off`)}
|
|
||||||
isChecked={host.enabled}
|
|
||||||
isDisabled={
|
|
||||||
toggleLoading ||
|
|
||||||
!host.summary_fields.user_capabilities.edit
|
|
||||||
}
|
|
||||||
onChange={() => onToggleHost(host)}
|
|
||||||
aria-label={i18n._(t`Toggle host`)}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</DataListCell>,
|
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{host.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Host`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/hosts/${host.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(
|
||||||
|
t`Indicates if a host is available and should be included in running jobs. For hosts that are part of an external inventory, this may be reset by the inventory sync process.`
|
||||||
|
)}
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
css="display: inline-flex;"
|
||||||
|
id={`host-${host.id}-toggle`}
|
||||||
|
label={i18n._(t`On`)}
|
||||||
|
labelOff={i18n._(t`Off`)}
|
||||||
|
isChecked={host.enabled}
|
||||||
|
isDisabled={
|
||||||
|
toggleLoading || !host.summary_fields.user_capabilities.edit
|
||||||
|
}
|
||||||
|
onChange={() => onToggleHost(host)}
|
||||||
|
aria-label={i18n._(t`Toggle host`)}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
{host.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Host`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/hosts/${host.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ function InventoryGroupDetail({ i18n, inventoryGroup }) {
|
|||||||
)}
|
)}
|
||||||
{error && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
isOpen={error}
|
isOpen={error}
|
||||||
onClose={() => setError(false)}
|
onClose={() => setError(false)}
|
||||||
|
|||||||
@@ -6,18 +6,17 @@ import { Group } from '@types';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
|
|
||||||
function InventoryGroupItem({
|
function InventoryGroupItem({
|
||||||
i18n,
|
i18n,
|
||||||
group,
|
group,
|
||||||
@@ -40,23 +39,26 @@ function InventoryGroupItem({
|
|||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="name">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`} id={labelId}>
|
<Link to={`${detailUrl}`} id={labelId}>
|
||||||
<b>{group.name}</b>
|
<b>{group.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{group.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Group`)} position="top">
|
|
||||||
<Button variant="plain" component={Link} to={editUrl}>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{group.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Group`)} position="top">
|
||||||
|
<Button variant="plain" component={Link} to={editUrl}>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -238,12 +238,14 @@ function InventoryGroupsList({ i18n, location, match }) {
|
|||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
canAdd && (
|
...(canAdd
|
||||||
<ToolbarAddButton
|
? [
|
||||||
key="add"
|
<ToolbarAddButton
|
||||||
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
key="add"
|
||||||
/>
|
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
||||||
),
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -259,7 +261,7 @@ function InventoryGroupsList({ i18n, location, match }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -98,46 +98,46 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
|
|
||||||
test('should check and uncheck the row item', async () => {
|
test('should check and uncheck the row item', async () => {
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-group-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').invoke('onChange')(
|
wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')(
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-group-1"]').props().checked
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').invoke('onChange')(
|
wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')(
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-group-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should check all row items when select all is checked', async () => {
|
test('should check all row items when select all is checked', async () => {
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(true);
|
expect(el.props().checked).toBe(true);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -157,7 +157,7 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
Promise.reject(new Error())
|
Promise.reject(new Error())
|
||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@@ -191,7 +191,7 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-group-1"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@@ -213,7 +213,7 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
.find('ModalBoxFooter Button[aria-label="Delete"]')
|
.find('ModalBoxFooter Button[aria-label="Delete"]')
|
||||||
.invoke('onClick')();
|
.invoke('onClick')();
|
||||||
});
|
});
|
||||||
await waitForElement(wrapper, { title: 'Error!', variant: 'danger' });
|
await waitForElement(wrapper, { title: 'Error!', variant: 'error' });
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('ModalBoxCloseButton').invoke('onClose')();
|
wrapper.find('ModalBoxCloseButton').invoke('onClose')();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,20 +4,27 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction as _DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Switch,
|
Switch,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
import Sparkline from '@components/Sparkline';
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import { Sparkline } from '@components/Sparkline';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { Host } from '@types';
|
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) {
|
function InventoryHostItem(props) {
|
||||||
const {
|
const {
|
||||||
@@ -50,7 +57,6 @@ function InventoryHostItem(props) {
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="divider">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{host.name}</b>
|
<b>{host.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -58,41 +64,42 @@ function InventoryHostItem(props) {
|
|||||||
<DataListCell key="recentJobs">
|
<DataListCell key="recentJobs">
|
||||||
<Sparkline jobs={recentPlaybookJobs} />
|
<Sparkline jobs={recentPlaybookJobs} />
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="enable" alignRight isFilled={false}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(
|
|
||||||
t`Indicates if a host is available and should be included
|
|
||||||
in running jobs. For hosts that are part of an external
|
|
||||||
inventory, this may be reset by the inventory sync process.`
|
|
||||||
)}
|
|
||||||
position="top"
|
|
||||||
>
|
|
||||||
<Switch
|
|
||||||
css="display: inline-flex;"
|
|
||||||
id={`host-${host.id}-toggle`}
|
|
||||||
label={i18n._(t`On`)}
|
|
||||||
labelOff={i18n._(t`Off`)}
|
|
||||||
isChecked={host.enabled}
|
|
||||||
isDisabled={
|
|
||||||
toggleLoading ||
|
|
||||||
!host.summary_fields.user_capabilities?.edit
|
|
||||||
}
|
|
||||||
onChange={() => toggleHost(host)}
|
|
||||||
aria-label={i18n._(t`Toggle host`)}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</DataListCell>,
|
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{host.summary_fields.user_capabilities?.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Host`)} position="top">
|
|
||||||
<Button variant="plain" component={Link} to={`${editUrl}`}>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(
|
||||||
|
t`Indicates if a host is available and should be included
|
||||||
|
in running jobs. For hosts that are part of an external
|
||||||
|
inventory, this may be reset by the inventory sync process.`
|
||||||
|
)}
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
css="display: inline-flex;"
|
||||||
|
id={`host-${host.id}-toggle`}
|
||||||
|
label={i18n._(t`On`)}
|
||||||
|
labelOff={i18n._(t`Off`)}
|
||||||
|
isChecked={host.enabled}
|
||||||
|
isDisabled={
|
||||||
|
toggleLoading || !host.summary_fields.user_capabilities?.edit
|
||||||
|
}
|
||||||
|
onChange={() => toggleHost(host)}
|
||||||
|
aria-label={i18n._(t`Toggle host`)}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
{host.summary_fields.user_capabilities?.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Host`)} position="top">
|
||||||
|
<Button variant="plain" component={Link} to={`${editUrl}`}>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -165,12 +165,14 @@ function InventoryHostList({ i18n, location, match }) {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName={i18n._(t`Hosts`)}
|
pluralizedItemName={i18n._(t`Hosts`)}
|
||||||
/>,
|
/>,
|
||||||
canAdd && (
|
...(canAdd
|
||||||
<ToolbarAddButton
|
? [
|
||||||
key="add"
|
<ToolbarAddButton
|
||||||
linkTo={`/inventories/inventory/${match.params.id}/hosts/add`}
|
key="add"
|
||||||
/>
|
linkTo={`/inventories/inventory/${match.params.id}/hosts/add`}
|
||||||
),
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -198,7 +200,7 @@ function InventoryHostList({ i18n, location, match }) {
|
|||||||
|
|
||||||
{toggleError && !toggleLoading && (
|
{toggleError && !toggleLoading && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
isOpen={toggleError && !toggleLoading}
|
isOpen={toggleError && !toggleLoading}
|
||||||
onClose={() => setToggleError(false)}
|
onClose={() => setToggleError(false)}
|
||||||
@@ -211,7 +213,7 @@ function InventoryHostList({ i18n, location, match }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -104,48 +104,48 @@ describe('<InventoryHostList />', () => {
|
|||||||
|
|
||||||
test('should check and uncheck the row item', async () => {
|
test('should check and uncheck the row item', async () => {
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-host-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').invoke('onChange')(
|
wrapper.find('DataListCheck[id="select-host-1"]').invoke('onChange')(
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-host-1"]').props().checked
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').invoke('onChange')(
|
wrapper.find('DataListCheck[id="select-host-1"]').invoke('onChange')(
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').props().checked
|
wrapper.find('DataListCheck[id="select-host-1"]').props().checked
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should check all row items when select all is checked', async () => {
|
test('should check all row items when select all is checked', async () => {
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(true);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(true);
|
expect(el.props().checked).toBe(true);
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
wrapper.find('Checkbox#select-all').invoke('onChange')(false);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('PFDataListCheck').forEach(el => {
|
wrapper.find('DataListCheck').forEach(el => {
|
||||||
expect(el.props().checked).toBe(false);
|
expect(el.props().checked).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -186,7 +186,7 @@ describe('<InventoryHostList />', () => {
|
|||||||
|
|
||||||
test('delete button is disabled if user does not have delete capabilities on a selected host', async () => {
|
test('delete button is disabled if user does not have delete capabilities on a selected host', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-3"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-host-3"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('ToolbarDeleteButton button').props().disabled).toBe(
|
expect(wrapper.find('ToolbarDeleteButton button').props().disabled).toBe(
|
||||||
@@ -197,7 +197,7 @@ describe('<InventoryHostList />', () => {
|
|||||||
test('should call api delete hosts for each selected host', async () => {
|
test('should call api delete hosts for each selected host', async () => {
|
||||||
HostsAPI.destroy = jest.fn();
|
HostsAPI.destroy = jest.fn();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-host-1"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@@ -220,7 +220,7 @@ describe('<InventoryHostList />', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-host-1"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@@ -242,7 +242,7 @@ describe('<InventoryHostList />', () => {
|
|||||||
Promise.reject(new Error())
|
Promise.reject(new Error())
|
||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('PFDataListCheck[id="select-host-1"]').invoke('onChange')();
|
wrapper.find('DataListCheck[id="select-host-1"]').invoke('onChange')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ class InventoriesList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName="Inventories"
|
pluralizedItemName="Inventories"
|
||||||
/>,
|
/>,
|
||||||
canAdd && addButton,
|
...(canAdd ? [addButton] : []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -231,7 +231,7 @@ class InventoriesList extends Component {
|
|||||||
</Card>
|
</Card>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ import { string, bool, func } from 'prop-types';
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { Inventory } from '@types';
|
import { Inventory } from '@types';
|
||||||
|
|
||||||
class InventoryListItem extends React.Component {
|
class InventoryListItem extends React.Component {
|
||||||
@@ -44,7 +44,6 @@ class InventoryListItem extends React.Component {
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="divider">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{inventory.name}</b>
|
<b>{inventory.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -54,25 +53,27 @@ class InventoryListItem extends React.Component {
|
|||||||
? i18n._(t`Smart Inventory`)
|
? i18n._(t`Smart Inventory`)
|
||||||
: i18n._(t`Inventory`)}
|
: i18n._(t`Inventory`)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{inventory.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Inventory`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/inventories/${
|
|
||||||
inventory.kind === 'smart'
|
|
||||||
? 'smart_inventory'
|
|
||||||
: 'inventory'
|
|
||||||
}/${inventory.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{inventory.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Inventory`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/inventories/${
|
||||||
|
inventory.kind === 'smart' ? 'smart_inventory' : 'inventory'
|
||||||
|
}/${inventory.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const InventoryGroupsDeleteModal = ({
|
|||||||
isOpen={isModalOpen}
|
isOpen={isModalOpen}
|
||||||
variant="danger"
|
variant="danger"
|
||||||
title={
|
title={
|
||||||
groups.length > 1 ? i18n._(t`Delete Groups`) : i18n._(t`Delete Group`)
|
groups.length > 1 ? i18n._(t`Delete Groups?`) : i18n._(t`Delete Group?`)
|
||||||
}
|
}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
actions={[
|
actions={[
|
||||||
@@ -60,7 +60,7 @@ const InventoryGroupsDeleteModal = ({
|
|||||||
return <ListItem key={group.id}>{group.name}</ListItem>;
|
return <ListItem key={group.id}>{group.name}</ListItem>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div css="padding-left: 1px;">
|
<div>
|
||||||
<Radio
|
<Radio
|
||||||
id="radio-delete"
|
id="radio-delete"
|
||||||
key="radio-delete"
|
key="radio-delete"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { VariablesInput as _VariablesInput } from '@components/CodeMirrorInput';
|
|||||||
import DeleteButton from '@components/DeleteButton';
|
import DeleteButton from '@components/DeleteButton';
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import LaunchButton from '@components/LaunchButton';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
import { formatDateString } from '@util/dates';
|
import { formatDateString } from '@util/dates';
|
||||||
import { Job } from '@types';
|
import { Job } from '@types';
|
||||||
@@ -275,7 +275,7 @@ function JobDetail({ job, i18n }) {
|
|||||||
{errorMsg && (
|
{errorMsg && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={errorMsg}
|
isOpen={errorMsg}
|
||||||
variant="danger"
|
variant="error"
|
||||||
onClose={() => setErrorMsg()}
|
onClose={() => setErrorMsg()}
|
||||||
title={i18n._(t`Job Delete Error`)}
|
title={i18n._(t`Job Delete Error`)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ function JobList({ i18n }) {
|
|||||||
</Card>
|
</Card>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={clearDeletionError}
|
onClose={clearDeletionError}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
start: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -34,6 +35,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
start: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -45,6 +47,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
start: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -56,6 +59,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
start: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -67,6 +71,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -78,6 +83,7 @@ const mockResults = [
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
DataListCell,
|
DataListCell,
|
||||||
DataListCheck,
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
@@ -14,32 +14,31 @@ import {
|
|||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { RocketIcon } from '@patternfly/react-icons';
|
import { RocketIcon } from '@patternfly/react-icons';
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import LaunchButton from '@components/LaunchButton';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
import { formatDateString } from '@util/dates';
|
import { formatDateString } from '@util/dates';
|
||||||
import { JOB_TYPE_URL_SEGMENTS } from '@constants';
|
import { JOB_TYPE_URL_SEGMENTS } from '@constants';
|
||||||
|
|
||||||
const PaddedIcon = styled(StatusIcon)`
|
|
||||||
margin-right: 20px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
class JobListItem extends Component {
|
class JobListItem extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { i18n, job, isSelected, onSelect } = this.props;
|
const { i18n, job, isSelected, onSelect } = this.props;
|
||||||
|
const labelId = `check-action-${job.id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataListItem aria-labelledby={`check-action-${job.id}`} id={`${job.id}`}>
|
<DataListItem aria-labelledby={labelId} id={`${job.id}`}>
|
||||||
<DataListItemRow>
|
<DataListItemRow>
|
||||||
<DataListCheck
|
<DataListCheck
|
||||||
id={`select-job-${job.id}`}
|
id={`select-job-${job.id}`}
|
||||||
checked={isSelected}
|
checked={isSelected}
|
||||||
onChange={onSelect}
|
onChange={onSelect}
|
||||||
aria-labelledby={`check-action-${job.id}`}
|
aria-labelledby={labelId}
|
||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="status" isFilled={false}>
|
||||||
{job.status && <PaddedIcon status={job.status} />}
|
{job.status && <StatusIcon status={job.status} />}
|
||||||
|
</DataListCell>,
|
||||||
|
<DataListCell key="name" css="display: inline-flex;">
|
||||||
<span>
|
<span>
|
||||||
<Link
|
<Link
|
||||||
to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}
|
to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}
|
||||||
@@ -54,22 +53,26 @@ class JobListItem extends Component {
|
|||||||
<DataListCell key="finished">
|
<DataListCell key="finished">
|
||||||
{formatDateString(job.finished)}
|
{formatDateString(job.finished)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell isFilled={false} alignRight key="relaunch">
|
|
||||||
{job.type !== 'system_job' &&
|
|
||||||
job.summary_fields.user_capabilities.start && (
|
|
||||||
<Tooltip content={i18n._(t`Relaunch Job`)} position="top">
|
|
||||||
<LaunchButton resource={job}>
|
|
||||||
{({ handleRelaunch }) => (
|
|
||||||
<Button variant="plain" onClick={handleRelaunch}>
|
|
||||||
<RocketIcon />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</LaunchButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
{job.type !== 'system_job' &&
|
||||||
|
job.summary_fields?.user_capabilities?.start && (
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
<Tooltip content={i18n._(t`Relaunch Job`)} position="top">
|
||||||
|
<LaunchButton resource={job}>
|
||||||
|
{({ handleRelaunch }) => (
|
||||||
|
<Button variant="plain" onClick={handleRelaunch}>
|
||||||
|
<RocketIcon />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</LaunchButton>
|
||||||
|
</Tooltip>
|
||||||
|
</DataListAction>
|
||||||
|
)}
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CodeMirrorInput from '@components/CodeMirrorInput';
|
|||||||
import ContentEmpty from '@components/ContentEmpty';
|
import ContentEmpty from '@components/ContentEmpty';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { DetailList, Detail } from '@components/DetailList';
|
import { DetailList, Detail } from '@components/DetailList';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { CardBody } from '@components/Card';
|
|||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
import ContentLoading from '@components/ContentLoading';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
|
|
||||||
import JobEvent from './JobEvent';
|
import JobEvent from './JobEvent';
|
||||||
import JobEventSkeleton from './JobEventSkeleton';
|
import JobEventSkeleton from './JobEventSkeleton';
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
TrashAltIcon,
|
TrashAltIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
import { Badge as PFBadge, Button, Tooltip } from '@patternfly/react-core';
|
import { Badge as PFBadge, Button, Tooltip } from '@patternfly/react-core';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import DeleteButton from '@components/DeleteButton';
|
import DeleteButton from '@components/DeleteButton';
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import LaunchButton from '@components/LaunchButton';
|
||||||
|
|
||||||
@@ -123,8 +122,6 @@ const OutputToolbar = ({ i18n, job, onDelete }) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</BadgeGroup>
|
</BadgeGroup>
|
||||||
|
|
||||||
<VerticalSeparator />
|
|
||||||
|
|
||||||
{job.type !== 'system_job' &&
|
{job.type !== 'system_job' &&
|
||||||
job.summary_fields.user_capabilities?.start && (
|
job.summary_fields.user_capabilities?.start && (
|
||||||
<Tooltip content={i18n._(t`Relaunch Job`)}>
|
<Tooltip content={i18n._(t`Relaunch Job`)}>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { func, shape } from 'prop-types';
|
import { func, shape } from 'prop-types';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import { WorkflowNodeTypeLetter } from '@components/Workflow';
|
import { WorkflowNodeTypeLetter } from '@components/Workflow';
|
||||||
import { secondsToHHMMSS } from '@util/dates';
|
import { secondsToHHMMSS } from '@util/dates';
|
||||||
import { constants as wfConstants } from '@components/Workflow/WorkflowUtils';
|
import { constants as wfConstants } from '@components/Workflow/WorkflowUtils';
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ import { t } from '@lingui/macro';
|
|||||||
import { shape } from 'prop-types';
|
import { shape } from 'prop-types';
|
||||||
import { Badge as PFBadge, Button, Tooltip } from '@patternfly/react-core';
|
import { Badge as PFBadge, Button, Tooltip } from '@patternfly/react-core';
|
||||||
import { CompassIcon, WrenchIcon } from '@patternfly/react-icons';
|
import { CompassIcon, WrenchIcon } from '@patternfly/react-icons';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const Toolbar = styled.div`
|
const Toolbar = styled.div`
|
||||||
align-items: center
|
align-items: center;
|
||||||
border-bottom: 1px solid grey;
|
border-bottom: 1px solid grey;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
@@ -73,7 +72,6 @@ function WorkflowOutputToolbar({ i18n, job }) {
|
|||||||
<ToolbarActions>
|
<ToolbarActions>
|
||||||
<div>{i18n._(t`Total Nodes`)}</div>
|
<div>{i18n._(t`Total Nodes`)}</div>
|
||||||
<Badge isRead>{totalNodes}</Badge>
|
<Badge isRead>{totalNodes}</Badge>
|
||||||
<VerticalSeparator />
|
|
||||||
<Tooltip content={i18n._(t`Toggle Legend`)} position="bottom">
|
<Tooltip content={i18n._(t`Toggle Legend`)} position="bottom">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
id="workflow-output-toggle-legend"
|
id="workflow-output-toggle-legend"
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ function OrganizationDetail({ i18n, organization }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -146,9 +146,9 @@ function OrganizationsList({ i18n }) {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName="Organizations"
|
pluralizedItemName="Organizations"
|
||||||
/>,
|
/>,
|
||||||
canAdd ? (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo={addUrl} />
|
? [<ToolbarAddButton key="add" linkTo={addUrl} />]
|
||||||
) : null,
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -169,7 +169,7 @@ function OrganizationsList({ i18n }) {
|
|||||||
</PageSection>
|
</PageSection>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={clearDeletionError}
|
onClose={clearDeletionError}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const mockOrganizations = {
|
|||||||
},
|
},
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -37,6 +38,7 @@ const mockOrganizations = {
|
|||||||
},
|
},
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -51,6 +53,7 @@ const mockOrganizations = {
|
|||||||
},
|
},
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,37 +5,29 @@ import { t } from '@lingui/macro';
|
|||||||
import {
|
import {
|
||||||
Badge as PFBadge,
|
Badge as PFBadge,
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { Organization } from '@types';
|
import { Organization } from '@types';
|
||||||
|
|
||||||
const Badge = styled(PFBadge)`
|
const Badge = styled(PFBadge)`
|
||||||
align-items: center;
|
margin-left: 8px;
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin-left: 10px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ListGroup = styled.span`
|
const ListGroup = styled.span`
|
||||||
display: flex;
|
margin-left: 24px;
|
||||||
margin-left: 40px;
|
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
&:first-of-type {
|
||||||
margin-left: 20px;
|
margin-left: 0;
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -63,7 +55,6 @@ function OrganizationListItem({
|
|||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="divider">
|
||||||
<VerticalSeparator />
|
|
||||||
<span id={labelId}>
|
<span id={labelId}>
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{organization.name}</b>
|
<b>{organization.name}</b>
|
||||||
@@ -84,21 +75,25 @@ function OrganizationListItem({
|
|||||||
</Badge>
|
</Badge>
|
||||||
</ListGroup>
|
</ListGroup>
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{organization.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Organization`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/organizations/${organization.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{organization.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Organization`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/organizations/${organization.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ function ProjectDetail({ project, i18n }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -206,9 +206,14 @@ class ProjectsList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName={i18n._(t`Projects`)}
|
pluralizedItemName={i18n._(t`Projects`)}
|
||||||
/>,
|
/>,
|
||||||
canAdd ? (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} />
|
? [
|
||||||
) : null,
|
<ToolbarAddButton
|
||||||
|
key="add"
|
||||||
|
linkTo={`${match.url}/add`}
|
||||||
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -231,7 +236,7 @@ class ProjectsList extends Component {
|
|||||||
</PageSection>
|
</PageSection>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { string, bool, func } from 'prop-types';
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction as _DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
DataListItemRow,
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
@@ -11,16 +14,20 @@ import {
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon, SyncIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon, SyncIcon } from '@patternfly/react-icons';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import ClipboardCopyButton from '@components/ClipboardCopyButton';
|
import ClipboardCopyButton from '@components/ClipboardCopyButton';
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import ProjectSyncButton from '../shared/ProjectSyncButton';
|
import ProjectSyncButton from '../shared/ProjectSyncButton';
|
||||||
import { StatusIcon } from '@components/Sparkline';
|
import StatusIcon from '@components/StatusIcon';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
import { Project } from '@types';
|
import { Project } from '@types';
|
||||||
|
|
||||||
|
const DataListAction = styled(_DataListAction)`
|
||||||
|
align-items: center;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 16px;
|
||||||
|
grid-template-columns: repeat(2, 40px);
|
||||||
|
`;
|
||||||
class ProjectListItem extends React.Component {
|
class ProjectListItem extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
project: Project.isRequired,
|
project: Project.isRequired,
|
||||||
@@ -73,8 +80,7 @@ class ProjectListItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="status" isFilled={false}>
|
||||||
<VerticalSeparator />
|
|
||||||
{project.summary_fields.last_job && (
|
{project.summary_fields.last_job && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
position="top"
|
position="top"
|
||||||
@@ -92,11 +98,9 @@ class ProjectListItem extends React.Component {
|
|||||||
</Link>
|
</Link>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Link
|
</DataListCell>,
|
||||||
id={labelId}
|
<DataListCell key="name">
|
||||||
to={`${detailUrl}`}
|
<Link id={labelId} to={`${detailUrl}`}>
|
||||||
css={{ marginLeft: '10px' }}
|
|
||||||
>
|
|
||||||
<b>{project.name}</b>
|
<b>{project.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
@@ -105,7 +109,7 @@ class ProjectListItem extends React.Component {
|
|||||||
? i18n._(t`Manual`)
|
? i18n._(t`Manual`)
|
||||||
: toTitleCase(project.scm_type)}
|
: toTitleCase(project.scm_type)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell alignRight isFilled={false} key="revision">
|
<DataListCell key="revision">
|
||||||
{project.scm_revision.substring(0, 7)}
|
{project.scm_revision.substring(0, 7)}
|
||||||
{project.scm_revision ? (
|
{project.scm_revision ? (
|
||||||
<ClipboardCopyButton
|
<ClipboardCopyButton
|
||||||
@@ -115,34 +119,41 @@ class ProjectListItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell alignRight isFilled={false} key="sync">
|
|
||||||
{project.summary_fields.user_capabilities.start && (
|
|
||||||
<Tooltip content={i18n._(t`Sync Project`)} position="top">
|
|
||||||
<ProjectSyncButton projectId={project.id}>
|
|
||||||
{handleSync => (
|
|
||||||
<Button variant="plain" onClick={handleSync}>
|
|
||||||
<SyncIcon />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</ProjectSyncButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{project.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Project`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/projects/${project.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{project.summary_fields.user_capabilities.start && (
|
||||||
|
<Tooltip content={i18n._(t`Sync Project`)} position="top">
|
||||||
|
<ProjectSyncButton projectId={project.id}>
|
||||||
|
{handleSync => (
|
||||||
|
<Button
|
||||||
|
css="grid-column: 1"
|
||||||
|
variant="plain"
|
||||||
|
onClick={handleSync}
|
||||||
|
>
|
||||||
|
<SyncIcon />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</ProjectSyncButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{project.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Project`)} position="top">
|
||||||
|
<Button
|
||||||
|
css="grid-column: 2"
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/projects/${project.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class ProjectSyncButton extends React.Component {
|
|||||||
{syncError && (
|
{syncError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={syncError}
|
isOpen={syncError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleSyncErrorClose}
|
onClose={this.handleSyncErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ function TeamDetail({ team, i18n }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -193,9 +193,14 @@ class TeamsList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName={i18n._(t`Teams`)}
|
pluralizedItemName={i18n._(t`Teams`)}
|
||||||
/>,
|
/>,
|
||||||
canAdd ? (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} />
|
? [
|
||||||
) : null,
|
<ToolbarAddButton
|
||||||
|
key="add"
|
||||||
|
linkTo={`${match.url}/add`}
|
||||||
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -218,7 +223,7 @@ class TeamsList extends Component {
|
|||||||
</PageSection>
|
</PageSection>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const mockAPITeamsList = {
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -27,6 +28,7 @@ const mockAPITeamsList = {
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -37,6 +39,7 @@ const mockAPITeamsList = {
|
|||||||
summary_fields: {
|
summary_fields: {
|
||||||
user_capabilities: {
|
user_capabilities: {
|
||||||
delete: true,
|
delete: true,
|
||||||
|
edit: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { Team } from '@types';
|
import { Team } from '@types';
|
||||||
|
|
||||||
class TeamListItem extends React.Component {
|
class TeamListItem extends React.Component {
|
||||||
@@ -28,6 +28,7 @@ class TeamListItem extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { team, isSelected, onSelect, detailUrl, i18n } = this.props;
|
const { team, isSelected, onSelect, detailUrl, i18n } = this.props;
|
||||||
const labelId = `check-action-${team.id}`;
|
const labelId = `check-action-${team.id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataListItem key={team.id} aria-labelledby={labelId} id={`${team.id}`}>
|
<DataListItem key={team.id} aria-labelledby={labelId} id={`${team.id}`}>
|
||||||
<DataListItemRow>
|
<DataListItemRow>
|
||||||
@@ -39,8 +40,7 @@ class TeamListItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="name">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link id={labelId} to={`${detailUrl}`}>
|
<Link id={labelId} to={`${detailUrl}`}>
|
||||||
<b>{team.name}</b>
|
<b>{team.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -48,9 +48,7 @@ class TeamListItem extends React.Component {
|
|||||||
<DataListCell key="organization">
|
<DataListCell key="organization">
|
||||||
{team.summary_fields.organization && (
|
{team.summary_fields.organization && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<b css={{ marginRight: '20px' }}>
|
<b css="margin-right: 24px">{i18n._(t`Organization`)}</b>
|
||||||
{i18n._(t`Organization`)}
|
|
||||||
</b>
|
|
||||||
<Link
|
<Link
|
||||||
to={`/organizations/${team.summary_fields.organization.id}/details`}
|
to={`/organizations/${team.summary_fields.organization.id}/details`}
|
||||||
>
|
>
|
||||||
@@ -59,21 +57,25 @@ class TeamListItem extends React.Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{team.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Team`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/teams/${team.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{team.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Team`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/teams/${team.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ function JobTemplateDetail({ i18n, template }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -121,21 +121,25 @@ function TemplateList({ i18n }) {
|
|||||||
const canAddWFJT =
|
const canAddWFJT =
|
||||||
wfjtActions && Object.prototype.hasOwnProperty.call(wfjtActions, 'POST');
|
wfjtActions && Object.prototype.hasOwnProperty.call(wfjtActions, 'POST');
|
||||||
const addButtonOptions = [];
|
const addButtonOptions = [];
|
||||||
|
|
||||||
if (canAddJT) {
|
if (canAddJT) {
|
||||||
addButtonOptions.push({
|
addButtonOptions.push({
|
||||||
label: i18n._(t`Template`),
|
label: i18n._(t`Template`),
|
||||||
url: `/templates/job_template/add/`,
|
url: `/templates/job_template/add/`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canAddWFJT) {
|
if (canAddWFJT) {
|
||||||
addButtonOptions.push({
|
addButtonOptions.push({
|
||||||
label: i18n._(t`Workflow Template`),
|
label: i18n._(t`Workflow Template`),
|
||||||
url: `/templates/workflow_job_template/add/`,
|
url: `/templates/workflow_job_template/add/`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const addButton = (
|
const addButton = (
|
||||||
<AddDropDownButton key="add" dropdownItems={addButtonOptions} />
|
<AddDropDownButton key="add" dropdownItems={addButtonOptions} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card>
|
<Card>
|
||||||
@@ -215,7 +219,7 @@ function TemplateList({ i18n }) {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName="Templates"
|
pluralizedItemName="Templates"
|
||||||
/>,
|
/>,
|
||||||
(canAddJT || canAddWFJT) && addButton,
|
...(canAddJT || canAddWFJT ? [addButton] : []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -234,7 +238,7 @@ function TemplateList({ i18n }) {
|
|||||||
</Card>
|
</Card>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={clearDeletionError}
|
onClose={clearDeletionError}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import React from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction as _DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
DataListItemRow,
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
@@ -15,14 +18,20 @@ import {
|
|||||||
RocketIcon,
|
RocketIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import LaunchButton from '@components/LaunchButton';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
import Sparkline from '@components/Sparkline';
|
||||||
import { Sparkline } from '@components/Sparkline';
|
|
||||||
import { toTitleCase } from '@util/strings';
|
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 }) {
|
function TemplateListItem({ i18n, template, isSelected, onSelect, detailUrl }) {
|
||||||
|
const labelId = `check-action-${template.id}`;
|
||||||
const canLaunch = template.summary_fields.user_capabilities.start;
|
const canLaunch = template.summary_fields.user_capabilities.start;
|
||||||
|
|
||||||
const missingResourceIcon =
|
const missingResourceIcon =
|
||||||
@@ -32,21 +41,17 @@ function TemplateListItem({ i18n, template, isSelected, onSelect, detailUrl }) {
|
|||||||
!template.ask_inventory_on_launch));
|
!template.ask_inventory_on_launch));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataListItem
|
<DataListItem aria-labelledby={labelId} id={`${template.id}`}>
|
||||||
aria-labelledby={`check-action-${template.id}`}
|
|
||||||
id={`${template.id}`}
|
|
||||||
>
|
|
||||||
<DataListItemRow>
|
<DataListItemRow>
|
||||||
<DataListCheck
|
<DataListCheck
|
||||||
id={`select-jobTemplate-${template.id}`}
|
id={`select-jobTemplate-${template.id}`}
|
||||||
checked={isSelected}
|
checked={isSelected}
|
||||||
onChange={onSelect}
|
onChange={onSelect}
|
||||||
aria-labelledby={`check-action-${template.id}`}
|
aria-labelledby={labelId}
|
||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="divider">
|
||||||
<VerticalSeparator />
|
|
||||||
<span>
|
<span>
|
||||||
<Link to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{template.name}</b>
|
<b>{template.name}</b>
|
||||||
@@ -71,34 +76,41 @@ function TemplateListItem({ i18n, template, isSelected, onSelect, detailUrl }) {
|
|||||||
<DataListCell key="sparkline">
|
<DataListCell key="sparkline">
|
||||||
<Sparkline jobs={template.summary_fields.recent_jobs} />
|
<Sparkline jobs={template.summary_fields.recent_jobs} />
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell alignRight isFilled={false} key="launch">
|
|
||||||
{canLaunch && template.type === 'job_template' && (
|
|
||||||
<Tooltip content={i18n._(t`Launch Template`)} position="top">
|
|
||||||
<LaunchButton resource={template}>
|
|
||||||
{({ handleLaunch }) => (
|
|
||||||
<Button variant="plain" onClick={handleLaunch}>
|
|
||||||
<RocketIcon />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</LaunchButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{template.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit Template`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/templates/${template.type}/${template.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{canLaunch && template.type === 'job_template' && (
|
||||||
|
<Tooltip content={i18n._(t`Launch Template`)} position="top">
|
||||||
|
<LaunchButton resource={template}>
|
||||||
|
{({ handleLaunch }) => (
|
||||||
|
<Button
|
||||||
|
css="grid-column: 1"
|
||||||
|
variant="plain"
|
||||||
|
onClick={handleLaunch}
|
||||||
|
>
|
||||||
|
<RocketIcon />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</LaunchButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{template.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Template`)} position="top">
|
||||||
|
<Button
|
||||||
|
css="grid-column: 2"
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/templates/${template.type}/${template.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
|||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
import { WorkflowJobTemplatesAPI } from '@api';
|
||||||
import {
|
import {
|
||||||
Chip,
|
Chip,
|
||||||
ChipGroup,
|
ChipGroup,
|
||||||
@@ -13,17 +14,16 @@ import {
|
|||||||
Label,
|
Label,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import { CardBody, CardActionsRow } from '@components/Card';
|
|
||||||
import ContentLoading from '@components/ContentLoading';
|
|
||||||
import { WorkflowJobTemplatesAPI } from '@api';
|
|
||||||
import AlertModal from '@components/AlertModal';
|
import AlertModal from '@components/AlertModal';
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
import { CardBody, CardActionsRow } from '@components/Card';
|
||||||
import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
|
|
||||||
import { VariablesDetail } from '@components/CodeMirrorInput';
|
import { VariablesDetail } from '@components/CodeMirrorInput';
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import DeleteButton from '@components/DeleteButton';
|
import DeleteButton from '@components/DeleteButton';
|
||||||
|
import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
|
||||||
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
|
import LaunchButton from '@components/LaunchButton';
|
||||||
|
import Sparkline from '@components/Sparkline';
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
import { Sparkline } from '@components/Sparkline';
|
|
||||||
|
|
||||||
function WorkflowJobTemplateDetail({ template, i18n, webHookKey }) {
|
function WorkflowJobTemplateDetail({ template, i18n, webHookKey }) {
|
||||||
const {
|
const {
|
||||||
@@ -104,7 +104,6 @@ function WorkflowJobTemplateDetail({ template, i18n, webHookKey }) {
|
|||||||
<Detail label={i18n._(t`Description`)} value={description} />
|
<Detail label={i18n._(t`Description`)} value={description} />
|
||||||
{summary_fields.recent_jobs?.length > 0 && (
|
{summary_fields.recent_jobs?.length > 0 && (
|
||||||
<Detail
|
<Detail
|
||||||
css="display: flex; flex: 1;"
|
|
||||||
value={<Sparkline jobs={recentPlaybookJobs} />}
|
value={<Sparkline jobs={recentPlaybookJobs} />}
|
||||||
label={i18n._(t`Activity`)}
|
label={i18n._(t`Activity`)}
|
||||||
/>
|
/>
|
||||||
@@ -223,7 +222,7 @@ function WorkflowJobTemplateDetail({ template, i18n, webHookKey }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ describe('NodeModal', () => {
|
|||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
@@ -136,7 +136,7 @@ describe('NodeModal', () => {
|
|||||||
wrapper.find('AnsibleSelect').prop('onChange')(null, 'project_sync');
|
wrapper.find('AnsibleSelect').prop('onChange')(null, 'project_sync');
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
@@ -166,7 +166,7 @@ describe('NodeModal', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
@@ -193,7 +193,7 @@ describe('NodeModal', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
@@ -396,7 +396,7 @@ describe('NodeModal', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button#next-node-modal').simulate('click');
|
wrapper.find('button#next-node-modal').simulate('click');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,19 +7,11 @@ import { Formik, Field } from 'formik';
|
|||||||
import { Form, FormGroup, TextInput } from '@patternfly/react-core';
|
import { Form, FormGroup, TextInput } from '@patternfly/react-core';
|
||||||
import FormRow from '@components/FormRow';
|
import FormRow from '@components/FormRow';
|
||||||
import AnsibleSelect from '@components/AnsibleSelect';
|
import AnsibleSelect from '@components/AnsibleSelect';
|
||||||
import VerticalSeperator from '@components/VerticalSeparator';
|
|
||||||
import InventorySourcesList from './InventorySourcesList';
|
import InventorySourcesList from './InventorySourcesList';
|
||||||
import JobTemplatesList from './JobTemplatesList';
|
import JobTemplatesList from './JobTemplatesList';
|
||||||
import ProjectsList from './ProjectsList';
|
import ProjectsList from './ProjectsList';
|
||||||
import WorkflowJobTemplatesList from './WorkflowJobTemplatesList';
|
import WorkflowJobTemplatesList from './WorkflowJobTemplatesList';
|
||||||
|
|
||||||
const Divider = styled.div`
|
|
||||||
height: 1px;
|
|
||||||
background-color: var(--pf-global--Color--light-300);
|
|
||||||
border: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TimeoutInput = styled(TextInput)`
|
const TimeoutInput = styled(TextInput)`
|
||||||
width: 200px;
|
width: 200px;
|
||||||
:not(:first-of-type) {
|
:not(:first-of-type) {
|
||||||
@@ -47,9 +39,8 @@ function NodeTypeStep({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div css=" display: flex; align-items: center; margin-bottom: 20px;">
|
<div css="display: flex; align-items: center; margin-bottom: 20px;">
|
||||||
<b>{i18n._(t`Node Type`)}</b>
|
<b css="margin-right: 24px">{i18n._(t`Node Type`)}</b>
|
||||||
<VerticalSeperator />
|
|
||||||
<div>
|
<div>
|
||||||
<AnsibleSelect
|
<AnsibleSelect
|
||||||
id="nodeResource-select"
|
id="nodeResource-select"
|
||||||
@@ -93,7 +84,6 @@ function NodeTypeStep({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider component="div" />
|
|
||||||
{nodeType === 'job_template' && (
|
{nodeType === 'job_template' && (
|
||||||
<JobTemplatesList
|
<JobTemplatesList
|
||||||
nodeResource={nodeResource}
|
nodeResource={nodeResource}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ describe('NodeTypeStep', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('AnsibleSelect').prop('value')).toBe('job_template');
|
expect(wrapper.find('AnsibleSelect').prop('value')).toBe('job_template');
|
||||||
expect(wrapper.find('JobTemplatesList').length).toBe(1);
|
expect(wrapper.find('JobTemplatesList').length).toBe(1);
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Job Template',
|
name: 'Test Job Template',
|
||||||
@@ -119,7 +119,7 @@ describe('NodeTypeStep', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('AnsibleSelect').prop('value')).toBe('project_sync');
|
expect(wrapper.find('AnsibleSelect').prop('value')).toBe('project_sync');
|
||||||
expect(wrapper.find('ProjectsList').length).toBe(1);
|
expect(wrapper.find('ProjectsList').length).toBe(1);
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
@@ -146,7 +146,7 @@ describe('NodeTypeStep', () => {
|
|||||||
'inventory_source_sync'
|
'inventory_source_sync'
|
||||||
);
|
);
|
||||||
expect(wrapper.find('InventorySourcesList').length).toBe(1);
|
expect(wrapper.find('InventorySourcesList').length).toBe(1);
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Inventory Source',
|
name: 'Test Inventory Source',
|
||||||
@@ -173,7 +173,7 @@ describe('NodeTypeStep', () => {
|
|||||||
'workflow_job_template'
|
'workflow_job_template'
|
||||||
);
|
);
|
||||||
expect(wrapper.find('WorkflowJobTemplatesList').length).toBe(1);
|
expect(wrapper.find('WorkflowJobTemplatesList').length).toBe(1);
|
||||||
wrapper.find('DataListRadio').simulate('click');
|
wrapper.find('Radio').simulate('click');
|
||||||
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
expect(onUpdateNodeResource).toHaveBeenCalledWith({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Workflow Job Template',
|
name: 'Test Workflow Job Template',
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ function VisualizerGraph({ i18n, readOnly }) {
|
|||||||
{linkHelp && <WorkflowLinkHelp link={linkHelp} />}
|
{linkHelp && <WorkflowLinkHelp link={linkHelp} />}
|
||||||
</WorkflowHelp>
|
</WorkflowHelp>
|
||||||
)}
|
)}
|
||||||
<WorkflowSVG id="workflow-svg" ref={svgRef} css="">
|
<WorkflowSVG id="workflow-svg" ref={svgRef}>
|
||||||
<defs>
|
<defs>
|
||||||
<marker
|
<marker
|
||||||
className="WorkflowChart-noPointerEvents"
|
className="WorkflowChart-noPointerEvents"
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ import {
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { func, shape } from 'prop-types';
|
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 {
|
import {
|
||||||
BookIcon,
|
BookIcon,
|
||||||
CompassIcon,
|
CompassIcon,
|
||||||
@@ -15,7 +20,6 @@ import {
|
|||||||
TrashAltIcon,
|
TrashAltIcon,
|
||||||
WrenchIcon,
|
WrenchIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const Badge = styled(PFBadge)`
|
const Badge = styled(PFBadge)`
|
||||||
@@ -51,15 +55,12 @@ function VisualizerToolbar({ i18n, onClose, onSave, template }) {
|
|||||||
return (
|
return (
|
||||||
<div id="visualizer-toolbar">
|
<div id="visualizer-toolbar">
|
||||||
<div css="align-items: center; border-bottom: 1px solid grey; display: flex; height: 56px; padding: 0px 20px;">
|
<div css="align-items: center; border-bottom: 1px solid grey; display: flex; height: 56px; padding: 0px 20px;">
|
||||||
<div css="display: flex;" id="visualizer-toolbar-template-name">
|
<Title size="xl">{template.name}</Title>
|
||||||
<b>{template.name}</b>
|
|
||||||
</div>
|
|
||||||
<div css="align-items: center; display: flex; flex: 1; justify-content: flex-end">
|
<div css="align-items: center; display: flex; flex: 1; justify-content: flex-end">
|
||||||
<div>{i18n._(t`Total Nodes`)}</div>
|
<div>{i18n._(t`Total Nodes`)}</div>
|
||||||
<Badge id="visualizer-total-nodes-badge" isRead>
|
<Badge id="visualizer-total-nodes-badge" isRead>
|
||||||
{totalNodes}
|
{totalNodes}
|
||||||
</Badge>
|
</Badge>
|
||||||
<VerticalSeparator />
|
|
||||||
<Tooltip content={i18n._(t`Toggle Legend`)} position="bottom">
|
<Tooltip content={i18n._(t`Toggle Legend`)} position="bottom">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
id="visualizer-toggle-legend"
|
id="visualizer-toggle-legend"
|
||||||
@@ -108,16 +109,15 @@ function VisualizerToolbar({ i18n, onClose, onSave, template }) {
|
|||||||
<TrashAltIcon />
|
<TrashAltIcon />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<VerticalSeparator />
|
|
||||||
<Button
|
<Button
|
||||||
id="visualizer-save"
|
id="visualizer-save"
|
||||||
|
css="margin: 0 32px"
|
||||||
aria-label={i18n._(t`Save`)}
|
aria-label={i18n._(t`Save`)}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
onClick={onSave}
|
onClick={onSave}
|
||||||
>
|
>
|
||||||
{i18n._(t`Save`)}
|
{i18n._(t`Save`)}
|
||||||
</Button>
|
</Button>
|
||||||
<VerticalSeparator />
|
|
||||||
<Button
|
<Button
|
||||||
id="visualizer-close"
|
id="visualizer-close"
|
||||||
aria-label={i18n._(t`Close`)}
|
aria-label={i18n._(t`Close`)}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ function UserDetail({ user, i18n }) {
|
|||||||
{deletionError && (
|
{deletionError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={() => setDeletionError(null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -197,9 +197,14 @@ class UsersList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
pluralizedItemName="Users"
|
pluralizedItemName="Users"
|
||||||
/>,
|
/>,
|
||||||
canAdd ? (
|
...(canAdd
|
||||||
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} />
|
? [
|
||||||
) : null,
|
<ToolbarAddButton
|
||||||
|
key="add"
|
||||||
|
linkTo={`${match.url}/add`}
|
||||||
|
/>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -222,7 +227,7 @@ class UsersList extends Component {
|
|||||||
</PageSection>
|
</PageSection>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={deletionError}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={this.handleDeleteErrorClose}
|
onClose={this.handleDeleteErrorClose}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListCell,
|
||||||
|
DataListCheck,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
|
DataListItemRow,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
|
||||||
import DataListCheck from '@components/DataListCheck';
|
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
|
||||||
import { User } from '@types';
|
import { User } from '@types';
|
||||||
|
|
||||||
class UserListItem extends React.Component {
|
class UserListItem extends React.Component {
|
||||||
@@ -39,8 +39,7 @@ class UserListItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key="divider">
|
<DataListCell key="username">
|
||||||
<VerticalSeparator />
|
|
||||||
<Link to={`${detailUrl}`} id={labelId}>
|
<Link to={`${detailUrl}`} id={labelId}>
|
||||||
<b>{user.username}</b>
|
<b>{user.username}</b>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -48,7 +47,7 @@ class UserListItem extends React.Component {
|
|||||||
<DataListCell key="first-name">
|
<DataListCell key="first-name">
|
||||||
{user.first_name && (
|
{user.first_name && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<b css={{ marginRight: '20px' }}>{i18n._(t`First Name`)}</b>
|
<b css="margin-right: 24px">{i18n._(t`First Name`)}</b>
|
||||||
{user.first_name}
|
{user.first_name}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
@@ -56,26 +55,30 @@ class UserListItem extends React.Component {
|
|||||||
<DataListCell key="last-name">
|
<DataListCell key="last-name">
|
||||||
{user.last_name && (
|
{user.last_name && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<b css={{ marginRight: '20px' }}>{i18n._(t`Last Name`)}</b>
|
<b css="margin-right: 24px">{i18n._(t`Last Name`)}</b>
|
||||||
{user.last_name}
|
{user.last_name}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="edit" alignRight isFilled={false}>
|
|
||||||
{user.summary_fields.user_capabilities.edit && (
|
|
||||||
<Tooltip content={i18n._(t`Edit User`)} position="top">
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
component={Link}
|
|
||||||
to={`/users/${user.id}/edit`}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</DataListCell>,
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{user.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit User`)} position="top">
|
||||||
|
<Button
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`/users/${user.id}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
</DataListItemRow>
|
</DataListItemRow>
|
||||||
</DataListItem>
|
</DataListItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -80,11 +80,7 @@ function UserForm({ user, handleCancel, handleSubmit, submitError, i18n }) {
|
|||||||
onSubmit={handleValidateAndSubmit}
|
onSubmit={handleValidateAndSubmit}
|
||||||
>
|
>
|
||||||
{formik => (
|
{formik => (
|
||||||
<Form
|
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||||
autoComplete="off"
|
|
||||||
onSubmit={formik.handleSubmit}
|
|
||||||
css="padding: 0 24px"
|
|
||||||
>
|
|
||||||
<FormRow>
|
<FormRow>
|
||||||
<FormField
|
<FormField
|
||||||
id="user-username"
|
id="user-username"
|
||||||
|
|||||||
Reference in New Issue
Block a user