1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-27 17:55:10 +03:00

Merge pull request #5085 from mabashian/5054-revision-column

Adds revision to project list row items

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
softwarefactory-project-zuul[bot] 2019-10-25 13:05:17 +00:00 committed by GitHub
commit d39ad9d9ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 143 additions and 0 deletions

View File

@ -0,0 +1,92 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Tooltip } from '@patternfly/react-core';
import { CopyIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const CopyButton = styled(Button)`
padding: 2px 4px;
margin-left: 8px;
border: none;
&:hover {
background-color: #0066cc;
color: white;
}
`;
export const clipboardCopyFunc = (event, text) => {
const clipboard = event.currentTarget.parentElement;
const el = document.createElement('input');
el.value = text;
clipboard.appendChild(el);
el.select();
document.execCommand('copy');
clipboard.removeChild(el);
};
class ClipboardCopyButton extends React.Component {
constructor(props) {
super(props);
this.state = {
copied: false,
};
this.handleCopyClick = this.handleCopyClick.bind(this);
}
handleCopyClick = event => {
const { stringToCopy, switchDelay } = this.props;
if (this.timer) {
window.clearTimeout(this.timer);
this.setState({ copied: false });
}
clipboardCopyFunc(event, stringToCopy);
this.setState({ copied: true }, () => {
this.timer = window.setTimeout(() => {
this.setState({ copied: false });
this.timer = null;
}, switchDelay);
});
};
render() {
const { clickTip, entryDelay, exitDelay, hoverTip } = this.props;
const { copied } = this.state;
return (
<Tooltip
entryDelay={entryDelay}
exitDelay={exitDelay}
trigger="mouseenter focus click"
content={copied ? clickTip : hoverTip}
>
<CopyButton
variant="plain"
onClick={this.handleCopyClick}
aria-label={hoverTip}
>
<CopyIcon />
</CopyButton>
</Tooltip>
);
}
}
ClipboardCopyButton.propTypes = {
clickTip: PropTypes.string.isRequired,
entryDelay: PropTypes.number,
exitDelay: PropTypes.number,
hoverTip: PropTypes.string.isRequired,
stringToCopy: PropTypes.string.isRequired,
switchDelay: PropTypes.number,
};
ClipboardCopyButton.defaultProps = {
entryDelay: 100,
exitDelay: 1600,
switchDelay: 2000,
};
export default ClipboardCopyButton;

View File

@ -0,0 +1,36 @@
import React from 'react';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
import ClipboardCopyButton from './ClipboardCopyButton';
document.execCommand = jest.fn();
jest.useFakeTimers();
describe('ClipboardCopyButton', () => {
test('renders the expected content', () => {
const wrapper = mountWithContexts(
<ClipboardCopyButton
clickTip="foo"
hoverTip="bar"
stringToCopy="foobar!"
/>
);
expect(wrapper).toHaveLength(1);
});
test('clicking button calls execCommand to copy to clipboard', () => {
const wrapper = mountWithContexts(
<ClipboardCopyButton
clickTip="foo"
hoverTip="bar"
stringToCopy="foobar!"
/>
).find('ClipboardCopyButton');
expect(wrapper.state('copied')).toBe(false);
wrapper.find('Button').simulate('click');
expect(document.execCommand).toBeCalledWith('copy');
expect(wrapper.state('copied')).toBe(true);
jest.runAllTimers();
wrapper.update();
expect(wrapper.state('copied')).toBe(false);
});
});

View File

@ -0,0 +1 @@
export { default } from './ClipboardCopyButton';

View File

@ -13,6 +13,7 @@ const mockProjects = [
url: '/api/v2/projects/1',
type: 'project',
scm_type: 'git',
scm_revision: 'hfadsh89sa9gsaisdf0jogos0fgd9sgdf89adsf98',
summary_fields: {
last_job: {
id: 9000,
@ -30,6 +31,7 @@ const mockProjects = [
url: '/api/v2/projects/2',
type: 'project',
scm_type: 'svn',
scm_revision: '7788f7erga0jijodfgsjisiodf98sdga9hg9a98gaf',
summary_fields: {
last_job: {
id: 9002,
@ -47,6 +49,7 @@ const mockProjects = [
url: '/api/v2/projects/3',
type: 'project',
scm_type: 'insights',
scm_revision: '4893adfi749493afjksjoaiosdgjoaisdjadfisjaso',
summary_fields: {
last_job: {
id: 9003,

View File

@ -12,6 +12,7 @@ import { Link as _Link } from 'react-router-dom';
import { SyncIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
import ClipboardCopyButton from '@components/ClipboardCopyButton';
import DataListCell from '@components/DataListCell';
import DataListCheck from '@components/DataListCheck';
import ListActionButton from '@components/ListActionButton';
@ -102,6 +103,14 @@ class ProjectListItem extends React.Component {
<DataListCell key="type">
{project.scm_type.toUpperCase()}
</DataListCell>,
<DataListCell key="revision">
{project.scm_revision.substring(0, 7)}
<ClipboardCopyButton
stringToCopy={project.scm_revision}
hoverTip={i18n._(t`Copy full revision to clipboard.`)}
clickTip={i18n._(t`Successfully copied to clipboard!`)}
/>
</DataListCell>,
<DataListCell lastcolumn="true" key="action">
{project.summary_fields.user_capabilities.start && (
<Tooltip content={i18n._(t`Sync Project`)} position="top">

View File

@ -17,6 +17,7 @@ describe('<ProjectsListItem />', () => {
url: '/api/v2/projects/1',
type: 'project',
scm_type: 'git',
scm_revision: '7788f7erga0jijodfgsjisiodf98sdga9hg9a98gaf',
summary_fields: {
last_job: {
id: 9000,
@ -43,6 +44,7 @@ describe('<ProjectsListItem />', () => {
url: '/api/v2/projects/1',
type: 'project',
scm_type: 'git',
scm_revision: '7788f7erga0jijodfgsjisiodf98sdga9hg9a98gaf',
summary_fields: {
last_job: {
id: 9000,