diff --git a/x-pack/legacy/plugins/code/common/commit_utils.test.ts b/x-pack/legacy/plugins/code/common/commit_utils.test.ts new file mode 100644 index 0000000000000..9deb15e9a26e7 --- /dev/null +++ b/x-pack/legacy/plugins/code/common/commit_utils.test.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { parseCommitMessage } from './commit_utils'; + +describe('Commit Utils', () => { + describe('parseCommitMessage', () => { + it('parses the summary from a commit message', () => { + const message = "This is a summary\n\nAnd here's the body"; + const { summary } = parseCommitMessage(message); + + expect(summary).toEqual('This is a summary'); + }); + + it('parses the body from a commit message', () => { + const message = "This is a summary\n\nAnd here's the body"; + const { body } = parseCommitMessage(message); + + expect(body).toEqual("And here's the body"); + }); + + it('includes the second line as body, if erroneously present', () => { + const messageWithSecondLine = 'summary\nsecond\ndescription'; + const { summary, body } = parseCommitMessage(messageWithSecondLine); + + expect(summary).toEqual('summary'); + expect(body).toEqual('second\ndescription'); + }); + }); +}); diff --git a/x-pack/legacy/plugins/code/common/commit_utils.ts b/x-pack/legacy/plugins/code/common/commit_utils.ts new file mode 100644 index 0000000000000..4a5a6d9f2da5a --- /dev/null +++ b/x-pack/legacy/plugins/code/common/commit_utils.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const parseCommitMessage: (message: string) => { summary: string; body: string } = message => { + const [summary, ...rest] = message.split('\n'); + const body = rest.join('\n').trim(); + + return { summary, body }; +}; + +export { parseCommitMessage }; diff --git a/x-pack/legacy/plugins/code/public/components/commits/__snapshots__/commit.test.tsx.snap b/x-pack/legacy/plugins/code/public/components/commits/__snapshots__/commit.test.tsx.snap new file mode 100644 index 0000000000000..fc4db9ed95bf1 --- /dev/null +++ b/x-pack/legacy/plugins/code/public/components/commits/__snapshots__/commit.test.tsx.snap @@ -0,0 +1,235 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Commit component renders correctly for a commit 1`] = ` + + +
+ +
+
+ +

+ This is my commit message +

+
+ +
+ + + + + Committed on 11/11/2222 by committer + + + + +
+
+ +
+

+ This is the description +

+
+
+
+ +
+ + + + + + + + + + + + + + +
+ 4ba67b8 +
+
+
+
+
+
+ + + + + +
+
+
+
+
+
+
+`; diff --git a/x-pack/legacy/plugins/code/public/components/commits/commit.test.tsx b/x-pack/legacy/plugins/code/public/components/commits/commit.test.tsx new file mode 100644 index 0000000000000..1c87f7cc72235 --- /dev/null +++ b/x-pack/legacy/plugins/code/public/components/commits/commit.test.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import toJson from 'enzyme-to-json'; + +import { Commit } from './commit'; +import { CommitInfo } from '../../../model/commit'; + +describe('Commit component', () => { + test('renders correctly for a commit', () => { + const commitInfo: CommitInfo = { + updated: new Date(Date.UTC(2222, 10, 11)), + message: 'This is my commit message\n\nThis is the description', + author: 'author', + committer: 'committer', + id: '4ba67b8', + parents: ['9817575'], + treeId: '96440ceb55e04a99d33c1c8ee021400a680fbf74', + }; + const wrapper = mount( + + ); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/legacy/plugins/code/public/components/commits/commit.tsx b/x-pack/legacy/plugins/code/public/components/commits/commit.tsx new file mode 100644 index 0000000000000..31020f6598393 --- /dev/null +++ b/x-pack/legacy/plugins/code/public/components/commits/commit.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { + EuiButtonIcon, + EuiButtonEmpty, + EuiFlexGroup, + EuiLink, + EuiPanel, + EuiText, + EuiTextColor, + EuiCopy, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CommitInfo } from '../../../model/commit'; +import { PathTypes } from '../../common/types'; +import { RepositoryUtils } from '../../../common/repository_utils'; +import { parseCommitMessage } from '../../../common/commit_utils'; + +const COMMIT_ID_LENGTH = 8; + +const RepoLink = ({ repoUri }: { repoUri: string }) => { + const repoOrg = RepositoryUtils.orgNameFromUri(repoUri); + const repoName = RepositoryUtils.repoNameFromUri(repoUri); + const repoPath = `#/${repoUri}`; + + return ( + <> + + {repoOrg} / {repoName} + + + • + + + ); +}; + +interface ActionProps { + repoUri: string; + commitId: string; +} + +const copyLabel = i18n.translate('xpack.code.commits.copyCommitAriaLabel', { + defaultMessage: 'Copy the full commit ID', +}); +const revisionLinkLabel = i18n.translate('xpack.code.commits.revisionLinkAriaLabel', { + defaultMessage: 'View the project at this commit', +}); + +const CommitActions = ({ commitId, repoUri }: ActionProps) => { + const revisionPath = `#/${repoUri}/${PathTypes.tree}/${commitId}`; + + return ( +
+ + {copy => } + + + {commitId} + + +
+ ); +}; + +interface Props { + commit: CommitInfo; + date: string; + repoUri: string; + showRepoLink: boolean; +} + +export const Commit = (props: Props) => { + const { date, commit, repoUri, showRepoLink } = props; + const { message, committer, id } = commit; + const { summary, body } = parseCommitMessage(message); + const commitId = id.substring(0, COMMIT_ID_LENGTH); + + return ( + + +
+ +

{summary}

+
+ + {showRepoLink && } + + + + + +

{body}

+
+
+ +
+
+ ); +}; diff --git a/x-pack/legacy/plugins/code/public/components/diff_page/commit_link.tsx b/x-pack/legacy/plugins/code/public/components/commits/commit_link.tsx similarity index 100% rename from x-pack/legacy/plugins/code/public/components/diff_page/commit_link.tsx rename to x-pack/legacy/plugins/code/public/components/commits/commit_link.tsx diff --git a/x-pack/legacy/plugins/code/public/components/commits/group.tsx b/x-pack/legacy/plugins/code/public/components/commits/group.tsx new file mode 100644 index 0000000000000..01c2844d38622 --- /dev/null +++ b/x-pack/legacy/plugins/code/public/components/commits/group.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTextColor } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CommitInfo } from '../../../model/commit'; +import { Commit } from './commit'; + +interface Props { + commits: CommitInfo[]; + date: string; + repoUri: string; +} + +export const CommitGroup = (props: Props) => { + const commitList = props.commits.map(commit => ( + + )); + + return ( +
+ + +
+ + + +

+ + + +

+
+
+ +
{commitList}
+
+ ); +}; diff --git a/x-pack/legacy/plugins/code/public/components/main/commit_history.tsx b/x-pack/legacy/plugins/code/public/components/commits/history.tsx similarity index 57% rename from x-pack/legacy/plugins/code/public/components/main/commit_history.tsx rename to x-pack/legacy/plugins/code/public/components/commits/history.tsx index e731c43fd439f..590e081dc2967 100644 --- a/x-pack/legacy/plugins/code/public/components/main/commit_history.tsx +++ b/x-pack/legacy/plugins/code/public/components/commits/history.tsx @@ -4,97 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiLoadingSpinner, - EuiPanel, - EuiText, - EuiTextColor, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - import _ from 'lodash'; import moment from 'moment'; import React from 'react'; import { connect } from 'react-redux'; import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { CommitGroup } from './group'; import { CommitInfo } from '../../../model/commit'; -import { CommitLink } from '../diff_page/commit_link'; import { RootState } from '../../reducers'; import { hasMoreCommitsSelector, treeCommitsSelector } from '../../selectors'; import { fetchMoreCommits } from '../../actions'; -const COMMIT_ID_LENGTH = 8; - -const Commit = (props: { commit: CommitInfo; date: string; repoUri: string }) => { - const { date, commit } = props; - const { message, committer, id } = commit; - const commitId = id - .split('') - .slice(0, COMMIT_ID_LENGTH) - .join(''); - return ( - -
- -

{message}

-
- - - {committer} · {date} - - -
-
- -
-
- ); -}; - -const CommitGroup = (props: { commits: CommitInfo[]; date: string; repoUri: string }) => { - const commitList = props.commits.map(commit => ( - - )); - return ( -
- - -
- - - -

- - {' '} - {} - -

-
-
- -
{commitList}
-
- ); -}; - -export const CommitHistoryLoading = () => ( +const CommitHistoryLoading = () => (
); -export const PageButtons = (props: { - loading?: boolean; - disabled: boolean; - onClick: () => void; -}) => ( +const PageButtons = (props: { loading?: boolean; disabled: boolean; onClick: () => void }) => (