From 410540701cca3651cbfb91f04affb51e49fe6f30 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 14:38:46 -0700 Subject: [PATCH 01/90] Add context menu for comments --- lib/views/reviews-view.js | 33 ++++++++++++++++++++++++++++++--- styles/review.less | 2 +- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index b323cb1c45..e8d8d01584 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -19,6 +19,8 @@ import Octicon from '../atom/octicon'; import RefHolder from '../models/ref-holder'; import {toNativePathSep, GHOST_USER} from '../helpers'; import {addEvent} from '../reporter-proxy'; +import {remote} from 'electron'; +const {Menu, MenuItem} = remote; const authorAssociationText = { MEMBER: 'Member', @@ -564,9 +566,11 @@ export default class ReviewsView extends React.Component { pending )} - - - + this.showActionsMenu(event, comment)} + />
{ + event.preventDefault(); + + const menu = new Menu(); + + menu.append(new MenuItem({ + label: 'Edit', + click: () => {}, + })); + + menu.append(new MenuItem({ + label: 'Open on GitHub', + click: () => {}, + })); + + menu.append(new MenuItem({ + label: 'Report abuse', + click: () => {}, + })); + + menu.popup(remote.getCurrentWindow()); + } + openFile = evt => { if (!this.props.checkoutOp.isEnabled()) { const target = evt.currentTarget; diff --git a/styles/review.less b/styles/review.less index f47ff464fb..54e39cf520 100644 --- a/styles/review.less +++ b/styles/review.less @@ -398,7 +398,7 @@ font-weight: 500; } - &-timeAgo, &-reportAbuseLink, &-edited { + &-timeAgo, &-actionsMenu, &-edited { color: @text-color-subtle; } From e0ab1dd250ff51ea31db8b310e7af1a559c37fe4 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 14:46:50 -0700 Subject: [PATCH 02/90] Add "Open on GitHub" menu item --- lib/views/reviews-view.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index e8d8d01584..cc7bd5295a 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -19,7 +19,7 @@ import Octicon from '../atom/octicon'; import RefHolder from '../models/ref-holder'; import {toNativePathSep, GHOST_USER} from '../helpers'; import {addEvent} from '../reporter-proxy'; -import {remote} from 'electron'; +import {remote, shell} from 'electron'; const {Menu, MenuItem} = remote; const authorAssociationText = { @@ -600,7 +600,7 @@ export default class ReviewsView extends React.Component { menu.append(new MenuItem({ label: 'Open on GitHub', - click: () => {}, + click: () => this.openOnGitHub(comment.url), })); menu.append(new MenuItem({ @@ -611,6 +611,17 @@ export default class ReviewsView extends React.Component { menu.popup(remote.getCurrentWindow()); } + openOnGitHub = url => { + return new Promise((resolve, reject) => { + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); + } + }); + }); + } + openFile = evt => { if (!this.props.checkoutOp.isEnabled()) { const target = evt.currentTarget; From e7e7a97d1399b85a69404f6a20a8af6b17f6f7aa Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 14:53:29 -0700 Subject: [PATCH 03/90] Add "Report abuse" menu item --- lib/views/reviews-view.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index cc7bd5295a..50a6dac99d 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -569,7 +569,7 @@ export default class ReviewsView extends React.Component { this.showActionsMenu(event, comment)} + onClick={event => this.showActionsMenu(event, comment, author)} />
@@ -588,7 +588,7 @@ export default class ReviewsView extends React.Component { ); } - showActionsMenu = (event, comment) => { + showActionsMenu = (event, comment, author) => { event.preventDefault(); const menu = new Menu(); @@ -605,12 +605,25 @@ export default class ReviewsView extends React.Component { menu.append(new MenuItem({ label: 'Report abuse', - click: () => {}, + click: () => this.reportAbuse(comment.url, author.login), })); menu.popup(remote.getCurrentWindow()); } + reportAbuse(commentUrl, author) { + return new Promise((resolve, reject) => { + const url = 'https://github.com/contact/report-content?report=' + + `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('report-abuse', {package: 'github', component: this.constructor.name}); + } + }); + }); + } + openOnGitHub = url => { return new Promise((resolve, reject) => { shell.openExternal(url, {}, err => { From 0eaf159512ebd4bd527e2d3b8585c39c2a60b468 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 14:54:23 -0700 Subject: [PATCH 04/90] Use arrow function to ensure proper this binding --- lib/views/reviews-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index 50a6dac99d..a4f5eb1d6b 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -611,7 +611,7 @@ export default class ReviewsView extends React.Component { menu.popup(remote.getCurrentWindow()); } - reportAbuse(commentUrl, author) { + reportAbuse = (commentUrl, author) => { return new Promise((resolve, reject) => { const url = 'https://github.com/contact/report-content?report=' + `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; From 8061849d66444d35e27429ba071526c7c1cae07c Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 15:49:25 -0700 Subject: [PATCH 05/90] Get comment body from graphql API --- ...tedReviewsContainerRefetchQuery.graphql.js | 22 +++++++++++++------ ...ommentDecorationsContainerQuery.graphql.js | 22 +++++++++++++------ .../issueishDetailContainerQuery.graphql.js | 22 +++++++++++++------ .../reviewsContainerQuery.graphql.js | 22 +++++++++++++------ .../reviewCommentsAccumulatorQuery.graphql.js | 22 +++++++++++++------ ...ommentsAccumulator_reviewThread.graphql.js | 20 ++++++++++++----- .../reviewThreadsAccumulatorQuery.graphql.js | 22 +++++++++++++------ .../review-comments-accumulator.js | 1 + 8 files changed, 105 insertions(+), 48 deletions(-) diff --git a/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js b/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js index ed22ebd6b6..2356980854 100644 --- a/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js +++ b/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash c78b6c8ea15f58b1de06a29e203fd1ad + * @relayHash bd491647ffb5d00bc7a6fda43e49b24c */ /* eslint-disable */ @@ -151,6 +151,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -742,7 +743,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -751,19 +752,19 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, - (v9/*: any*/), - (v15/*: any*/), { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "isMinimized", "args": null, "storageKey": null }, + (v9/*: any*/), + (v15/*: any*/), { "kind": "LinkedField", "alias": null, @@ -780,6 +781,13 @@ return { (v3/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -833,7 +841,7 @@ return { "operationKind": "query", "name": "aggregatedReviewsContainerRefetchQuery", "id": null, - "text": "query aggregatedReviewsContainerRefetchQuery(\n $prId: ID!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n pullRequest: node(id: $prId) {\n __typename\n ...prCheckoutController_pullRequest\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query aggregatedReviewsContainerRefetchQuery(\n $prId: ID!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n pullRequest: node(id: $prId) {\n __typename\n ...prCheckoutController_pullRequest\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js b/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js index 6a2394c3d5..33eabd125a 100644 --- a/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js +++ b/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 02603333f5d8b5bed9e192b81fe49e1d + * @relayHash 69c4c588d263da91c8a3313401b3f84c */ /* eslint-disable */ @@ -184,6 +184,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -895,7 +896,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -904,19 +905,19 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, - (v15/*: any*/), - (v21/*: any*/), { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "isMinimized", "args": null, "storageKey": null }, + (v15/*: any*/), + (v21/*: any*/), { "kind": "LinkedField", "alias": null, @@ -933,6 +934,13 @@ return { (v9/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -992,7 +1000,7 @@ return { "operationKind": "query", "name": "commentDecorationsContainerQuery", "id": null, - "text": "query commentDecorationsContainerQuery(\n $headOwner: String!\n $headName: String!\n $headRef: String!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n $first: Int!\n) {\n repository(owner: $headOwner, name: $headName) {\n ref(qualifiedName: $headRef) {\n associatedPullRequests(first: $first, states: [OPEN]) {\n totalCount\n nodes {\n number\n headRefOid\n ...commentDecorationsController_pullRequests\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n }\n id\n }\n id\n }\n}\n\nfragment commentDecorationsController_pullRequests on PullRequest {\n number\n headRefName\n headRefOid\n headRepository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query commentDecorationsContainerQuery(\n $headOwner: String!\n $headName: String!\n $headRef: String!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n $first: Int!\n) {\n repository(owner: $headOwner, name: $headName) {\n ref(qualifiedName: $headRef) {\n associatedPullRequests(first: $first, states: [OPEN]) {\n totalCount\n nodes {\n number\n headRefOid\n ...commentDecorationsController_pullRequests\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n }\n id\n }\n id\n }\n}\n\nfragment commentDecorationsController_pullRequests on PullRequest {\n number\n headRefName\n headRefOid\n headRepository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js b/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js index 8cddd318d5..54bb685f4d 100644 --- a/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js +++ b/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 669f6411c4085a7670d22aca11164bb8 + * @relayHash 71f729826c2a840c9f278c2f94365c57 */ /* eslint-disable */ @@ -627,6 +627,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -960,14 +961,14 @@ v23 = [ v24 = { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, v25 = { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "position", "args": null, "storageKey": null }, @@ -1595,6 +1596,13 @@ return { (v24/*: any*/), (v4/*: any*/), (v13/*: any*/), + { + "kind": "ScalarField", + "alias": null, + "name": "body", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -1604,7 +1612,6 @@ return { }, (v11/*: any*/), (v20/*: any*/), - (v25/*: any*/), { "kind": "LinkedField", "alias": null, @@ -1621,6 +1628,7 @@ return { (v4/*: any*/) ] }, + (v25/*: any*/), (v26/*: any*/), (v12/*: any*/), (v5/*: any*/), @@ -2125,8 +2133,8 @@ return { (v44/*: any*/), (v13/*: any*/), (v26/*: any*/), - (v25/*: any*/), - (v24/*: any*/) + (v24/*: any*/), + (v25/*: any*/) ] } ] @@ -2210,7 +2218,7 @@ return { "operationKind": "query", "name": "issueishDetailContainerQuery", "id": null, - "text": "query issueishDetailContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $issueishNumber: Int!\n $timelineCount: Int!\n $timelineCursor: String\n $commitCount: Int!\n $commitCursor: String\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n issueish: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n }\n ... on Node {\n id\n }\n }\n ...issueishDetailController_repository_1mXVvq\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment issueishDetailController_repository_1mXVvq on Repository {\n ...issueDetailView_repository\n ...prCheckoutController_repository\n ...prDetailView_repository\n name\n owner {\n __typename\n login\n id\n }\n issue: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on Issue {\n title\n number\n ...issueDetailView_issue_3D8CP9\n }\n ... on Node {\n id\n }\n }\n pullRequest: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n title\n number\n ...prCheckoutController_pullRequest\n ...prDetailView_pullRequest_1TnD8A\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment issueDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment issueDetailView_issue_3D8CP9 on Issue {\n id\n __typename\n url\n state\n number\n title\n bodyHTML\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...issueTimelineController_issue_3D8CP9\n ...emojiReactionsView_reactable\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment prDetailView_pullRequest_1TnD8A on PullRequest {\n id\n __typename\n url\n isCrossRepository\n changedFiles\n state\n number\n title\n bodyHTML\n baseRefName\n headRefName\n countedCommits: commits {\n totalCount\n }\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...prCommitsView_pullRequest_38TpXw\n ...prStatusesView_pullRequest\n ...prTimelineController_pullRequest_3D8CP9\n ...emojiReactionsController_reactable\n}\n\nfragment prCommitsView_pullRequest_38TpXw on PullRequest {\n url\n commits(first: $commitCount, after: $commitCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n commit {\n id\n ...prCommitView_item\n }\n id\n __typename\n }\n }\n }\n}\n\nfragment prStatusesView_pullRequest on PullRequest {\n id\n recentCommits: commits(last: 1) {\n edges {\n node {\n commit {\n status {\n state\n contexts {\n id\n state\n ...prStatusContextView_context\n }\n id\n }\n id\n }\n id\n }\n }\n }\n}\n\nfragment prTimelineController_pullRequest_3D8CP9 on PullRequest {\n url\n ...headRefForcePushedEventView_issueish\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...mergedEventView_item\n ...headRefForcePushedEventView_item\n ...commitCommentThreadView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment headRefForcePushedEventView_issueish on PullRequest {\n headRefName\n headRepositoryOwner {\n __typename\n login\n id\n }\n repository {\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment commitsView_nodes on Commit {\n id\n author {\n name\n user {\n login\n id\n }\n }\n ...commitView_commit\n}\n\nfragment issueCommentView_item on IssueComment {\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n bodyHTML\n createdAt\n url\n}\n\nfragment mergedEventView_item on MergedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n mergeRefName\n createdAt\n}\n\nfragment headRefForcePushedEventView_item on HeadRefForcePushedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n beforeCommit {\n oid\n id\n }\n afterCommit {\n oid\n id\n }\n createdAt\n}\n\nfragment commitCommentThreadView_item on CommitCommentThread {\n commit {\n oid\n id\n }\n comments(first: 100) {\n edges {\n node {\n id\n ...commitCommentView_item\n }\n }\n }\n}\n\nfragment crossReferencedEventsView_nodes on CrossReferencedEvent {\n id\n referencedAt\n isCrossRepository\n actor {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n source {\n __typename\n ... on RepositoryNode {\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n ...crossReferencedEventView_item\n}\n\nfragment crossReferencedEventView_item on CrossReferencedEvent {\n id\n isCrossRepository\n source {\n __typename\n ... on Issue {\n number\n title\n url\n issueState: state\n }\n ... on PullRequest {\n number\n title\n url\n prState: state\n }\n ... on RepositoryNode {\n repository {\n name\n isPrivate\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment commitCommentView_item on CommitComment {\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n bodyHTML\n createdAt\n path\n position\n}\n\nfragment commitView_commit on Commit {\n author {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n committer {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n authoredByCommitter\n sha: oid\n message\n messageHeadlineHTML\n commitUrl\n}\n\nfragment prStatusContextView_context on StatusContext {\n context\n description\n state\n targetUrl\n}\n\nfragment prCommitView_item on Commit {\n committer {\n avatarUrl\n name\n date\n }\n messageHeadline\n messageBody\n shortSha: abbreviatedOid\n sha: oid\n url\n}\n\nfragment issueTimelineController_issue_3D8CP9 on Issue {\n url\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n", + "text": "query issueishDetailContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $issueishNumber: Int!\n $timelineCount: Int!\n $timelineCursor: String\n $commitCount: Int!\n $commitCursor: String\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n issueish: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n }\n ... on Node {\n id\n }\n }\n ...issueishDetailController_repository_1mXVvq\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment issueishDetailController_repository_1mXVvq on Repository {\n ...issueDetailView_repository\n ...prCheckoutController_repository\n ...prDetailView_repository\n name\n owner {\n __typename\n login\n id\n }\n issue: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on Issue {\n title\n number\n ...issueDetailView_issue_3D8CP9\n }\n ... on Node {\n id\n }\n }\n pullRequest: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n title\n number\n ...prCheckoutController_pullRequest\n ...prDetailView_pullRequest_1TnD8A\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment issueDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment issueDetailView_issue_3D8CP9 on Issue {\n id\n __typename\n url\n state\n number\n title\n bodyHTML\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...issueTimelineController_issue_3D8CP9\n ...emojiReactionsView_reactable\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment prDetailView_pullRequest_1TnD8A on PullRequest {\n id\n __typename\n url\n isCrossRepository\n changedFiles\n state\n number\n title\n bodyHTML\n baseRefName\n headRefName\n countedCommits: commits {\n totalCount\n }\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...prCommitsView_pullRequest_38TpXw\n ...prStatusesView_pullRequest\n ...prTimelineController_pullRequest_3D8CP9\n ...emojiReactionsController_reactable\n}\n\nfragment prCommitsView_pullRequest_38TpXw on PullRequest {\n url\n commits(first: $commitCount, after: $commitCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n commit {\n id\n ...prCommitView_item\n }\n id\n __typename\n }\n }\n }\n}\n\nfragment prStatusesView_pullRequest on PullRequest {\n id\n recentCommits: commits(last: 1) {\n edges {\n node {\n commit {\n status {\n state\n contexts {\n id\n state\n ...prStatusContextView_context\n }\n id\n }\n id\n }\n id\n }\n }\n }\n}\n\nfragment prTimelineController_pullRequest_3D8CP9 on PullRequest {\n url\n ...headRefForcePushedEventView_issueish\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...mergedEventView_item\n ...headRefForcePushedEventView_item\n ...commitCommentThreadView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment headRefForcePushedEventView_issueish on PullRequest {\n headRefName\n headRepositoryOwner {\n __typename\n login\n id\n }\n repository {\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment commitsView_nodes on Commit {\n id\n author {\n name\n user {\n login\n id\n }\n }\n ...commitView_commit\n}\n\nfragment issueCommentView_item on IssueComment {\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n bodyHTML\n createdAt\n url\n}\n\nfragment mergedEventView_item on MergedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n mergeRefName\n createdAt\n}\n\nfragment headRefForcePushedEventView_item on HeadRefForcePushedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n beforeCommit {\n oid\n id\n }\n afterCommit {\n oid\n id\n }\n createdAt\n}\n\nfragment commitCommentThreadView_item on CommitCommentThread {\n commit {\n oid\n id\n }\n comments(first: 100) {\n edges {\n node {\n id\n ...commitCommentView_item\n }\n }\n }\n}\n\nfragment crossReferencedEventsView_nodes on CrossReferencedEvent {\n id\n referencedAt\n isCrossRepository\n actor {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n source {\n __typename\n ... on RepositoryNode {\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n ...crossReferencedEventView_item\n}\n\nfragment crossReferencedEventView_item on CrossReferencedEvent {\n id\n isCrossRepository\n source {\n __typename\n ... on Issue {\n number\n title\n url\n issueState: state\n }\n ... on PullRequest {\n number\n title\n url\n prState: state\n }\n ... on RepositoryNode {\n repository {\n name\n isPrivate\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment commitCommentView_item on CommitComment {\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n bodyHTML\n createdAt\n path\n position\n}\n\nfragment commitView_commit on Commit {\n author {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n committer {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n authoredByCommitter\n sha: oid\n message\n messageHeadlineHTML\n commitUrl\n}\n\nfragment prStatusContextView_context on StatusContext {\n context\n description\n state\n targetUrl\n}\n\nfragment prCommitView_item on Commit {\n committer {\n avatarUrl\n name\n date\n }\n messageHeadline\n messageBody\n shortSha: abbreviatedOid\n sha: oid\n url\n}\n\nfragment issueTimelineController_issue_3D8CP9 on Issue {\n url\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/reviewsContainerQuery.graphql.js b/lib/containers/__generated__/reviewsContainerQuery.graphql.js index f1adb901d9..008d201904 100644 --- a/lib/containers/__generated__/reviewsContainerQuery.graphql.js +++ b/lib/containers/__generated__/reviewsContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash c5fc2c138b012df8081c275fb687ae7b + * @relayHash 866aa50eb10fa07fd2692696ee8166e7 */ /* eslint-disable */ @@ -187,6 +187,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -826,7 +827,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -835,19 +836,19 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, - (v13/*: any*/), - (v19/*: any*/), { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "isMinimized", "args": null, "storageKey": null }, + (v13/*: any*/), + (v19/*: any*/), { "kind": "LinkedField", "alias": null, @@ -864,6 +865,13 @@ return { (v7/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -968,7 +976,7 @@ return { "operationKind": "query", "name": "reviewsContainerQuery", "id": null, - "text": "query reviewsContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $prNumber: Int!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n ...reviewsController_repository\n pullRequest(number: $prNumber) {\n headRefOid\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n ...reviewsController_pullRequest\n id\n }\n id\n }\n viewer {\n ...reviewsController_viewer\n id\n }\n}\n\nfragment reviewsController_repository on Repository {\n ...prCheckoutController_repository\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewsController_pullRequest on PullRequest {\n id\n ...prCheckoutController_pullRequest\n}\n\nfragment reviewsController_viewer on User {\n id\n login\n avatarUrl\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n", + "text": "query reviewsContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $prNumber: Int!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n ...reviewsController_repository\n pullRequest(number: $prNumber) {\n headRefOid\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n ...reviewsController_pullRequest\n id\n }\n id\n }\n viewer {\n ...reviewsController_viewer\n id\n }\n}\n\nfragment reviewsController_repository on Repository {\n ...prCheckoutController_repository\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewsController_pullRequest on PullRequest {\n id\n ...prCheckoutController_pullRequest\n}\n\nfragment reviewsController_viewer on User {\n id\n login\n avatarUrl\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js b/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js index de2e349eaa..e2a463e3f9 100644 --- a/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash e03fe8d7e5ac69de56d1ba99eb403ce7 + * @relayHash e9b1697b85a36fcbb4a8071b04ab4558 */ /* eslint-disable */ @@ -63,6 +63,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -289,7 +290,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -304,28 +305,28 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "state", + "name": "isMinimized", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "viewerCanReact", + "name": "state", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "viewerCanReact", "args": null, "storageKey": null }, @@ -357,6 +358,13 @@ return { (v3/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -448,7 +456,7 @@ return { "operationKind": "query", "name": "reviewCommentsAccumulatorQuery", "id": null, - "text": "query reviewCommentsAccumulatorQuery(\n $id: ID!\n $commentCount: Int!\n $commentCursor: String\n) {\n node(id: $id) {\n __typename\n ... on PullRequestReviewThread {\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n }\n id\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query reviewCommentsAccumulatorQuery(\n $id: ID!\n $commentCount: Int!\n $commentCursor: String\n) {\n node(id: $id) {\n __typename\n ... on PullRequestReviewThread {\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n }\n id\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js b/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js index a049a16ac9..84c0c755e9 100644 --- a/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js @@ -30,6 +30,7 @@ export type reviewCommentsAccumulator_reviewThread = {| +url: any, |}, +bodyHTML: any, + +body: string, +isMinimized: boolean, +state: PullRequestReviewCommentState, +viewerCanReact: boolean, @@ -157,7 +158,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -172,28 +173,28 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "state", + "name": "isMinimized", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "viewerCanReact", + "name": "state", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "viewerCanReact", "args": null, "storageKey": null }, @@ -223,6 +224,13 @@ return { (v1/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -267,5 +275,5 @@ return { }; })(); // prettier-ignore -(node/*: any*/).hash = '6a1d075c882842171dfeaf52d4241b35'; +(node/*: any*/).hash = 'd5a80482dbc1e2684264d0e88bfe90b3'; module.exports = node; diff --git a/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js b/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js index 3ac5f6b86d..d209d8493b 100644 --- a/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 3b12f0de40249adb03e03e305bb72247 + * @relayHash ae118b6a8035c1d13132cdeed250a0b6 */ /* eslint-disable */ @@ -92,6 +92,7 @@ fragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThrea } } bodyHTML + body isMinimized state viewerCanReact @@ -412,7 +413,7 @@ return { { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -427,28 +428,28 @@ return { { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "body", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "state", + "name": "isMinimized", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "viewerCanReact", + "name": "state", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "viewerCanReact", "args": null, "storageKey": null }, @@ -474,6 +475,13 @@ return { (v3/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "position", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -581,7 +589,7 @@ return { "operationKind": "query", "name": "reviewThreadsAccumulatorQuery", "id": null, - "text": "query reviewThreadsAccumulatorQuery(\n $url: URI!\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewThreadsAccumulator_pullRequest_3dVVow\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_3dVVow on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1UlnwR\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThread {\n id\n comments(first: $commentCount) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query reviewThreadsAccumulatorQuery(\n $url: URI!\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewThreadsAccumulator_pullRequest_3dVVow\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_3dVVow on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1UlnwR\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThread {\n id\n comments(first: $commentCount) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/review-comments-accumulator.js b/lib/containers/accumulators/review-comments-accumulator.js index 1bebdffed1..603d76bb71 100644 --- a/lib/containers/accumulators/review-comments-accumulator.js +++ b/lib/containers/accumulators/review-comments-accumulator.js @@ -70,6 +70,7 @@ export default createPaginationContainer(BareReviewCommentsAccumulator, { url } bodyHTML + body isMinimized state viewerCanReact From d49149c997026ae87ecae971ad64098406f2e580 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 16:21:00 -0700 Subject: [PATCH 06/90] Extract ReviewCommentView So that it can manage its own edit state --- lib/views/review-comment-view.js | 122 +++++++++++++++++++++++++++++++ lib/views/reviews-view.js | 120 ++++-------------------------- 2 files changed, 137 insertions(+), 105 deletions(-) create mode 100644 lib/views/review-comment-view.js diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js new file mode 100644 index 0000000000..f3da48c19d --- /dev/null +++ b/lib/views/review-comment-view.js @@ -0,0 +1,122 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cx from 'classnames'; +import {remote, shell} from 'electron'; +const {Menu, MenuItem} = remote; + +import Timeago from './timeago'; +import Octicon from '../atom/octicon'; +import GithubDotcomMarkdown from './github-dotcom-markdown'; +import EmojiReactionsController from '../controllers/emoji-reactions-controller'; +import {GHOST_USER} from '../helpers'; +import {addEvent} from '../reporter-proxy'; + +export default class ReviewCommentView extends React.Component { + static propTypes = { + + } + + render() { + const comment = this.props.comment; + + if (comment.isMinimized) { + return ( +
+ + This comment was hidden +
+ ); + } + + const commentClass = cx('github-Review-comment', {'github-Review-comment--pending': comment.state === 'PENDING'}); + const author = comment.author || GHOST_USER; + + return ( +
+
+
+ {author.login} + + {author.login} + + + + + {this.props.renderEditedLink(comment)} + {this.props.renderAuthorAssociation(comment)} + {comment.state === 'PENDING' && ( + pending + )} +
+ this.showActionsMenu(event, comment, author)} + /> +
+
+ + +
+
+ ); + } + + showActionsMenu = (event, comment, author) => { + event.preventDefault(); + + const menu = new Menu(); + + menu.append(new MenuItem({ + label: 'Edit', + click: () => {}, + })); + + menu.append(new MenuItem({ + label: 'Open on GitHub', + click: () => this.openOnGitHub(comment.url), + })); + + menu.append(new MenuItem({ + label: 'Report abuse', + click: () => this.reportAbuse(comment.url, author.login), + })); + + menu.popup(remote.getCurrentWindow()); + } + + + reportAbuse = (commentUrl, author) => { + return new Promise((resolve, reject) => { + const url = 'https://github.com/contact/report-content?report=' + + `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('report-abuse', {package: 'github', component: this.constructor.name}); + } + }); + }); + } + + openOnGitHub = url => { + return new Promise((resolve, reject) => { + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); + } + }); + }); + } +} diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index a4f5eb1d6b..726c5721e9 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -13,14 +13,12 @@ import EmojiReactionsController from '../controllers/emoji-reactions-controller' import {checkoutStates} from '../controllers/pr-checkout-controller'; import GithubDotcomMarkdown from './github-dotcom-markdown'; import PatchPreviewView from './patch-preview-view'; +import ReviewCommentView from './review-comment-view'; import CheckoutButton from './checkout-button'; import Timeago from './timeago'; -import Octicon from '../atom/octicon'; import RefHolder from '../models/ref-holder'; import {toNativePathSep, GHOST_USER} from '../helpers'; import {addEvent} from '../reporter-proxy'; -import {remote, shell} from 'electron'; -const {Menu, MenuItem} = remote; const authorAssociationText = { MEMBER: 'Member', @@ -457,7 +455,20 @@ export default class ReviewsView extends React.Component {
- {comments.map(this.renderComment)} + {comments.map(comment => { + return ( + + ); + })}
{ - if (comment.isMinimized) { - return ( -
- - This comment was hidden -
- ); - } - - const commentClass = cx('github-Review-comment', {'github-Review-comment--pending': comment.state === 'PENDING'}); - const author = comment.author || GHOST_USER; - - return ( -
-
-
- {author.login} - - {author.login} - - - - - {this.renderEditedLink(comment)} - {this.renderAuthorAssociation(comment)} - {comment.state === 'PENDING' && ( - pending - )} -
- this.showActionsMenu(event, comment, author)} - /> -
-
- - -
-
- ); - } - - showActionsMenu = (event, comment, author) => { - event.preventDefault(); - - const menu = new Menu(); - - menu.append(new MenuItem({ - label: 'Edit', - click: () => {}, - })); - - menu.append(new MenuItem({ - label: 'Open on GitHub', - click: () => this.openOnGitHub(comment.url), - })); - - menu.append(new MenuItem({ - label: 'Report abuse', - click: () => this.reportAbuse(comment.url, author.login), - })); - - menu.popup(remote.getCurrentWindow()); - } - - reportAbuse = (commentUrl, author) => { - return new Promise((resolve, reject) => { - const url = 'https://github.com/contact/report-content?report=' + - `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('report-abuse', {package: 'github', component: this.constructor.name}); - } - }); - }); - } - - openOnGitHub = url => { - return new Promise((resolve, reject) => { - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); - } - }); - }); - } - openFile = evt => { if (!this.props.checkoutOp.isEnabled()) { const target = evt.currentTarget; From 1c13cad8f2878b42ce98f903d8de450394fb9979 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 17:14:44 -0700 Subject: [PATCH 07/90] Display editor when "Edit" menu item is clicked --- lib/views/review-comment-view.js | 52 +++++++++++++++++++++++++++++++- lib/views/reviews-view.js | 1 + styles/review.less | 2 +- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index f3da48c19d..f7aedc12f6 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -3,20 +3,70 @@ import PropTypes from 'prop-types'; import cx from 'classnames'; import {remote, shell} from 'electron'; const {Menu, MenuItem} = remote; +import {TextBuffer} from 'atom'; + import Timeago from './timeago'; import Octicon from '../atom/octicon'; +import AtomTextEditor from '../atom/atom-text-editor'; import GithubDotcomMarkdown from './github-dotcom-markdown'; import EmojiReactionsController from '../controllers/emoji-reactions-controller'; import {GHOST_USER} from '../helpers'; import {addEvent} from '../reporter-proxy'; +import RefHolder from '../models/ref-holder'; export default class ReviewCommentView extends React.Component { static propTypes = { } + constructor(props) { + super(props); + + this.refEditor = new RefHolder(); + + this.state = {editing: false}; + } + render() { + return this.state.editing ? this.renderEditor() : this.renderComment(); + } + + renderEditor() { + const buffer = new TextBuffer(); + buffer.setText(this.props.comment.body); + + return ( +
+ +
+ + +
+
+ ); + } + + renderComment() { const comment = this.props.comment; if (comment.isMinimized) { @@ -79,7 +129,7 @@ export default class ReviewCommentView extends React.Component { menu.append(new MenuItem({ label: 'Edit', - click: () => {}, + click: () => this.setState({editing: true}), })); menu.append(new MenuItem({ diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index 726c5721e9..18f38dd68f 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -466,6 +466,7 @@ export default class ReviewsView extends React.Component { reportMutationErrors={this.props.reportMutationErrors} renderEditedLink={this.renderEditedLink} renderAuthorAssociation={this.renderAuthorAssociation} + isPosting={isPosting} /> ); })} diff --git a/styles/review.less b/styles/review.less index 54e39cf520..dbe98b46c1 100644 --- a/styles/review.less +++ b/styles/review.less @@ -418,7 +418,7 @@ } } - &-reply { + &-reply, &-editComment { margin-top: @component-padding; atom-text-editor { From d0fb685919c9623c73040142ca1c86589a319de1 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Fri, 3 May 2019 17:33:54 -0700 Subject: [PATCH 08/90] Cancel editing message, prompting first if text had been changed --- lib/containers/reviews-container.js | 1 + lib/controllers/reviews-controller.js | 1 + lib/controllers/root-controller.js | 1 + lib/items/reviews-item.js | 1 + lib/views/review-comment-view.js | 14 +++++++++++++- lib/views/reviews-view.js | 2 ++ 6 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/containers/reviews-container.js b/lib/containers/reviews-container.js index 45b62d6afa..af5663d1e4 100644 --- a/lib/containers/reviews-container.js +++ b/lib/containers/reviews-container.js @@ -40,6 +40,7 @@ export default class ReviewsContainer extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, + confirm: PropTypes.object.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 3c2255d4db..f956f6c936 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -64,6 +64,7 @@ export class BareReviewsController extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, + confirm: PropTypes.object.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/controllers/root-controller.js b/lib/controllers/root-controller.js index ae64fffa77..6fcdba7057 100644 --- a/lib/controllers/root-controller.js +++ b/lib/controllers/root-controller.js @@ -462,6 +462,7 @@ export default class RootController extends React.Component { tooltips={this.props.tooltips} config={this.props.config} commands={this.props.commandRegistry} + confirm={this.props.confirm} reportMutationErrors={this.reportMutationErrors} /> )} diff --git a/lib/items/reviews-item.js b/lib/items/reviews-item.js index 8edb7263c5..f989e99cbc 100644 --- a/lib/items/reviews-item.js +++ b/lib/items/reviews-item.js @@ -25,6 +25,7 @@ export default class ReviewsItem extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, + confirm: PropTypes.object.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index f7aedc12f6..285f7d5c8f 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -51,7 +51,7 @@ export default class ReviewCommentView extends React.Component { className="github-Review-editCommentCancelButton btn" title="Cancel editing comment" disabled={this.props.isPosting} - onClick={() => {}}> + onClick={() => this.onCancel(buffer.getText())}> Cancel ); @@ -533,7 +533,7 @@ export default class ReviewsView extends React.Component { ); @@ -623,4 +623,23 @@ export default class ReviewsView extends React.Component { return {lineNumber, positionText}; } + + scrollToThread(threadID) { + const threadHolder = this.threadHolders.get(threadID); + if (threadHolder) { + threadHolder.map(element => { + element.scrollIntoViewIfNeeded(); + return null; // shh, eslint + }); + } + } + + async resolveUnresolveThread(thread) { + if (thread.isResolved) { + await this.props.unresolveThread(thread); + } else { + await this.props.resolveThread(thread); + } + this.scrollToThread(thread.id); + } } From 23472c6cf6f7800e5d4d31e238475d6555ee62cc Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 1 May 2019 20:22:54 -0400 Subject: [PATCH 33/90] remove duplications --- lib/views/reviews-view.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index c4fb2248dc..f0a32fdefa 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -111,26 +111,14 @@ export default class ReviewsView extends React.Component { componentDidMount() { const {scrollToThreadID} = this.props; if (scrollToThreadID) { - const threadHolder = this.threadHolders.get(scrollToThreadID); - if (threadHolder) { - threadHolder.map(element => { - element.scrollIntoViewIfNeeded(); - return null; // shh, eslint - }); - } + this.scrollToThread(scrollToThreadID); } } componentDidUpdate(prevProps) { const {scrollToThreadID} = this.props; if (scrollToThreadID && scrollToThreadID !== prevProps.scrollToThreadID) { - const threadHolder = this.threadHolders.get(scrollToThreadID); - if (threadHolder) { - threadHolder.map(element => { - element.scrollIntoViewIfNeeded(); - return null; // shh, eslint - }); - } + this.scrollToThread(scrollToThreadID); } } From e69e2fad768c6a35ce22147c904ae0efa45f1fba Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 2 May 2019 10:05:58 -0400 Subject: [PATCH 34/90] i slept on it and decided that was a bad idea. --- lib/views/reviews-view.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index f0a32fdefa..ce51c1da0e 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -628,6 +628,5 @@ export default class ReviewsView extends React.Component { } else { await this.props.resolveThread(thread); } - this.scrollToThread(thread.id); } } From 0bd304c1f42c68df76f6f5996435864ed13adc60 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 2 May 2019 12:24:56 -0400 Subject: [PATCH 35/90] add missing proptype --- lib/views/reviews-view.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index ce51c1da0e..ad2c85d1d1 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -54,6 +54,9 @@ export default class ReviewsView extends React.Component { threadIDsOpen: PropTypes.shape({ has: PropTypes.func.isRequired, }), + highlightedThreadIDs: PropTypes.shape({ + has: PropTypes.func.isRequired, + }), postingToThreadID: PropTypes.string, scrollToThreadID: PropTypes.string, // Structure: Map< relativePath: String, { From 6e6e718e6244f567046a08795d1e35688d33b226 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 2 May 2019 12:40:19 -0400 Subject: [PATCH 36/90] fix tests --- lib/controllers/reviews-controller.js | 3 +++ test/views/reviews-view.test.js | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index b1dce06f64..e920df133e 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -240,6 +240,9 @@ export class BareReviewsController extends React.Component { }, () => { setTimeout(() => this.setState(state => { state.highlightedThreadIDs.delete(threadID); + if (state.scrollToThreadID === threadID) { + return {scrollToThreadID: null}; + } return {}; }), FLASH_DELAY); }); diff --git a/test/views/reviews-view.test.js b/test/views/reviews-view.test.js index 3b3d8a09cf..8253d7cbbe 100644 --- a/test/views/reviews-view.test.js +++ b/test/views/reviews-view.test.js @@ -36,6 +36,7 @@ describe('ReviewsView', function() { summarySectionOpen: true, commentSectionOpen: true, threadIDsOpen: new Set(), + highlightedThreadIDs: new Set(), number: 100, repo: 'github', From 764a81f64dcde97e975274d17ee0a4f6a49ac1a8 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 2 May 2019 13:18:14 -0400 Subject: [PATCH 37/90] styling --- styles/review.less | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/styles/review.less b/styles/review.less index 5dc8e7a68b..5213877780 100644 --- a/styles/review.less +++ b/styles/review.less @@ -79,9 +79,13 @@ border-bottom: 0; padding-left: @component-padding; .github-Reviews { - &-title, &-header { + &-title { color: @text-color-subtle; } + &-header { + color: @text-color-subtle; + padding-top: @component-padding * 0.5; + } } } } From 5dbefe9393a586d2e6561b69bda4da473ef26be9 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 6 May 2019 08:25:38 -0400 Subject: [PATCH 38/90] Default upstream refspec to `master` --- actions/schema-up/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/schema-up/index.js b/actions/schema-up/index.js index db4c34f2bd..2e602601cb 100644 --- a/actions/schema-up/index.js +++ b/actions/schema-up/index.js @@ -42,7 +42,7 @@ Toolkit.run(async tools => { if (hasRelayChanges === 0 && !relayFailed) { tools.log.info('Generated relay files are unchanged.'); - const upstream = tools.context.ref.replace(/^refs\/heads\//, ''); + const upstream = tools.context.ref || 'master'; await tools.runInWorkspace('git', ['push', 'origin', upstream]); tools.exit.success('Schema is up to date on master.'); } From 8a09603e259f9f8e6af86ec5c6ad23488a939e10 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 6 May 2019 08:30:19 -0400 Subject: [PATCH 39/90] Let's try again tonight --- .github/main.workflow | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/main.workflow b/.github/main.workflow index 490262a3b2..c02769775e 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -1,6 +1,6 @@ workflow "GraphQL schema update" { - // Every Monday at 1am. - on = "schedule(0 1 * * 1)" + // Every Tuesday at 1am. + on = "schedule(0 2 * * 1)" resolves = "Update schema" } From 123eca4c21ad060929d4f1bf5eb62f3150a72f26 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 6 May 2019 13:10:18 -0400 Subject: [PATCH 40/90] Cron syntax is hard --- .github/main.workflow | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/main.workflow b/.github/main.workflow index c02769775e..e62af80adf 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -1,6 +1,6 @@ workflow "GraphQL schema update" { // Every Tuesday at 1am. - on = "schedule(0 2 * * 1)" + on = "schedule(0 1 * * 2)" resolves = "Update schema" } From 6b06b8c0fb1ba882e9987019a5d7e4486de3d03c Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Mon, 6 May 2019 15:09:46 -0400 Subject: [PATCH 41/90] add/modify some tests --- lib/controllers/reviews-controller.js | 2 +- lib/views/reviews-view.js | 1 + test/controllers/reviews-controller.test.js | 8 ++++++-- test/views/reviews-view.test.js | 7 +++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index e920df133e..e21d0721ec 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -14,7 +14,7 @@ import unresolveReviewThreadMutation from '../mutations/unresolve-review-thread' import IssueishDetailItem from '../items/issueish-detail-item'; import {addEvent} from '../reporter-proxy'; -// Milliseconds to leave scrollToThreadID non-null before reverting. +// Milliseconds to update highlightedThreadIDs const FLASH_DELAY = 1500; export class BareReviewsController extends React.Component { diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index ad2c85d1d1..7084f593f4 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -615,6 +615,7 @@ export default class ReviewsView extends React.Component { return {lineNumber, positionText}; } + /* istanbul ignore next */ scrollToThread(threadID) { const threadHolder = this.threadHolders.get(threadID); if (threadHolder) { diff --git a/test/controllers/reviews-controller.test.js b/test/controllers/reviews-controller.test.js index 35f6c90b63..471e6ec3aa 100644 --- a/test/controllers/reviews-controller.test.js +++ b/test/controllers/reviews-controller.test.js @@ -95,20 +95,22 @@ describe('ReviewsController', function() { assert.strictEqual(opWrapper.find(ReviewsView).prop('extra'), extra); }); - it('scrolls to a specific thread on mount', function() { + it('scrolls to and highlight a specific thread on mount', function() { clock = sinon.useFakeTimers(); const wrapper = shallow(buildApp({initThreadID: 'thread0'})); let opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); assert.include(opWrapper.find(ReviewsView).prop('threadIDsOpen'), 'thread0'); + assert.include(opWrapper.find(ReviewsView).prop('highlightedThreadIDs'), 'thread0'); assert.strictEqual(opWrapper.find(ReviewsView).prop('scrollToThreadID'), 'thread0'); clock.tick(2000); opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + assert.notInclude(opWrapper.find(ReviewsView).prop('highlightedThreadIDs'), 'thread0'); assert.isNull(opWrapper.find(ReviewsView).prop('scrollToThreadID')); }); - it('scrolls to a specific thread on update', function() { + it('scrolls to and highlight a specific thread on update', function() { clock = sinon.useFakeTimers(); const wrapper = shallow(buildApp()); let opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); @@ -118,11 +120,13 @@ describe('ReviewsController', function() { opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); assert.include(opWrapper.find(ReviewsView).prop('threadIDsOpen'), 'hang-by-a-thread'); + assert.include(opWrapper.find(ReviewsView).prop('highlightedThreadIDs'), 'hang-by-a-thread'); assert.isTrue(opWrapper.find(ReviewsView).prop('commentSectionOpen')); assert.strictEqual(opWrapper.find(ReviewsView).prop('scrollToThreadID'), 'hang-by-a-thread'); clock.tick(2000); opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + assert.notInclude(opWrapper.find(ReviewsView).prop('highlightedThreadIDs'), 'hang-by-a-thread'); assert.isNull(opWrapper.find(ReviewsView).prop('scrollToThreadID')); }); diff --git a/test/views/reviews-view.test.js b/test/views/reviews-view.test.js index 8253d7cbbe..efacc4a504 100644 --- a/test/views/reviews-view.test.js +++ b/test/views/reviews-view.test.js @@ -319,6 +319,13 @@ describe('ReviewsView', function() { assert.strictEqual(comment.find('em').text(), 'This comment was hidden'); }); + it('groups comments by their resolved status', function() { + const unresolvedThreads = wrapper.find('.github-Reviews-section.comments').find('.github-Review'); + const resolvedThreads = wrapper.find('.github-Reviews-section.resolved-comments').find('.github-Review'); + assert.lengthOf(resolvedThreads, 1); + assert.lengthOf(unresolvedThreads, 3); + }); + describe('indication that a comment has been edited', function() { it('indicates that a review summary comment has been edited', function() { const summary = wrapper.find('.github-ReviewSummary').at(0); From e5177eadd430cfb3998095a7c91c5c268a03fb64 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Tue, 7 May 2019 09:58:33 -0400 Subject: [PATCH 42/90] Use a full refspec and only use HEAD locally --- actions/schema-up/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/schema-up/index.js b/actions/schema-up/index.js index 2e602601cb..2908d39637 100644 --- a/actions/schema-up/index.js +++ b/actions/schema-up/index.js @@ -42,7 +42,7 @@ Toolkit.run(async tools => { if (hasRelayChanges === 0 && !relayFailed) { tools.log.info('Generated relay files are unchanged.'); - const upstream = tools.context.ref || 'master'; + const upstream = tools.context.ref || 'HEAD:refs/heads/master'; await tools.runInWorkspace('git', ['push', 'origin', upstream]); tools.exit.success('Schema is up to date on master.'); } From f89aa4d9e84d55e755a399282cf2ba6b99d2bc79 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Tue, 7 May 2019 09:59:00 -0400 Subject: [PATCH 43/90] On to wednesday :calendar: --- .github/main.workflow | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/main.workflow b/.github/main.workflow index e62af80adf..a2e3c22b0b 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -1,6 +1,6 @@ workflow "GraphQL schema update" { - // Every Tuesday at 1am. - on = "schedule(0 1 * * 2)" + // Every Wednesday at 1am. + on = "schedule(0 1 * * 3)" resolves = "Update schema" } From e6e02f2c3ba51cfd8b2835727be01c01099bc36a Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 8 Apr 2019 13:46:16 -0400 Subject: [PATCH 44/90] Prepare 0.28.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b53342b533..8f76c6199f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "github", "main": "./lib/index", - "version": "0.26.0", + "version": "0.28.0", "description": "GitHub integration", "repository": "https://github.com/atom/github", "license": "MIT", From 5d34670bf7774f01d567adc6fa4cb19b4f9a2d90 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Wed, 8 May 2019 08:50:13 -0400 Subject: [PATCH 45/90] Prepare 0.29.0 release --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15b3492905..b0ebaaf7f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "github", - "version": "0.26.0", + "version": "0.29.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7742,7 +7742,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -7865,7 +7865,7 @@ }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, diff --git a/package.json b/package.json index 8f76c6199f..f17e3ef237 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "github", "main": "./lib/index", - "version": "0.28.0", + "version": "0.29.0", "description": "GitHub integration", "repository": "https://github.com/atom/github", "license": "MIT", From 53816048856d10b64d88dd95c510f0ce9aeea0f9 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 13:42:45 -0400 Subject: [PATCH 46/90] add missing proptypes --- lib/views/review-comment-view.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index 285f7d5c8f..e2385138bb 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -17,7 +17,15 @@ import RefHolder from '../models/ref-holder'; export default class ReviewCommentView extends React.Component { static propTypes = { - + comment: PropTypes.object.isRequired, + isPosting: PropTypes.bool.isRequired, + confirm: PropTypes.object.isRequired, + tooltips: PropTypes.object.isRequired, + renderEditedLink: PropTypes.func.isRequired, + renderAuthorAssociation: PropTypes.func.isRequired, + reportMutationErrors: PropTypes.func.isRequired, + openIssueish: PropTypes.func.isRequired, + openIssueishLinkInNewTab: PropTypes.func.isRequired, } constructor(props) { From 4f0048f3f23fa55802969308f25ba2c1777b35c5 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 13:52:04 -0400 Subject: [PATCH 47/90] add some styling for the footer buttons --- styles/review.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/styles/review.less b/styles/review.less index 5213877780..9f3ea9eabd 100644 --- a/styles/review.less +++ b/styles/review.less @@ -458,6 +458,16 @@ padding: 0 2*@component-padding; } + &-editComment-footer { + margin: @component-padding/2 0 @component-padding 0; + display: flex; + justify-content: flex-end; + + .btn { + margin-left: @component-padding/2; + } + } + // Footer ------------------ From 45642407fddb92b2dcb49c7e8c4aaf4b47882b40 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 13:58:30 -0400 Subject: [PATCH 48/90] add empty edit comment function --- lib/controllers/reviews-controller.js | 3 ++ lib/views/review-comment-view.js | 41 ++++++++++++++------------- lib/views/reviews-view.js | 1 + 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index e21d0721ec..61437cf1ce 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -145,6 +145,7 @@ export class BareReviewsController extends React.Component { resolveThread={this.resolveThread} unresolveThread={this.unresolveThread} addSingleComment={this.addSingleComment} + editComment={this.editComment} {...this.props} /> )} @@ -343,6 +344,8 @@ export class BareReviewsController extends React.Component { this.setState({postingToThreadID: null}); } } + + editComment = newCommentBody => {} } export default createFragmentContainer(BareReviewsController, { diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index e2385138bb..17fcb2a59b 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -26,6 +26,7 @@ export default class ReviewCommentView extends React.Component { reportMutationErrors: PropTypes.func.isRequired, openIssueish: PropTypes.func.isRequired, openIssueishLinkInNewTab: PropTypes.func.isRequired, + editComment: PropTypes.func.isRequired, } constructor(props) { @@ -166,27 +167,27 @@ export default class ReviewCommentView extends React.Component { } - reportAbuse = (commentUrl, author) => { - return new Promise((resolve, reject) => { - const url = 'https://github.com/contact/report-content?report=' + - `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('report-abuse', {package: 'github', component: this.constructor.name}); - } - }); + reportAbuse = (commentUrl, author) => { + return new Promise((resolve, reject) => { + const url = 'https://github.com/contact/report-content?report=' + + `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('report-abuse', {package: 'github', component: this.constructor.name}); + } }); - } + }); + } - openOnGitHub = url => { - return new Promise((resolve, reject) => { - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); - } - }); + openOnGitHub = url => { + return new Promise((resolve, reject) => { + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); + } }); - } + }); + } } diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index 7084f593f4..ececaed158 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -96,6 +96,7 @@ export default class ReviewsView extends React.Component { resolveThread: PropTypes.func.isRequired, unresolveThread: PropTypes.func.isRequired, addSingleComment: PropTypes.func.isRequired, + editComment: PropTypes.func.isRequired, reportMutationErrors: PropTypes.func.isRequired, } From d970678cea22e126a61a78c934d71541008401fb Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 16:22:38 -0400 Subject: [PATCH 49/90] drill em props --- lib/controllers/reviews-controller.js | 6 ++++-- lib/views/review-comment-view.js | 19 +++++++++++++++---- lib/views/reviews-view.js | 3 ++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 61437cf1ce..63252bf94d 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -145,7 +145,7 @@ export class BareReviewsController extends React.Component { resolveThread={this.resolveThread} unresolveThread={this.unresolveThread} addSingleComment={this.addSingleComment} - editComment={this.editComment} + updateComment={this.updateComment} {...this.props} /> )} @@ -345,7 +345,9 @@ export class BareReviewsController extends React.Component { } } - editComment = newCommentBody => {} + updateComment = (commentId, commentBody, callback) => { + + } } export default createFragmentContainer(BareReviewsController, { diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index 17fcb2a59b..fab4ce0ffe 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -26,7 +26,7 @@ export default class ReviewCommentView extends React.Component { reportMutationErrors: PropTypes.func.isRequired, openIssueish: PropTypes.func.isRequired, openIssueishLinkInNewTab: PropTypes.func.isRequired, - editComment: PropTypes.func.isRequired, + updateComment: PropTypes.func.isRequired, } constructor(props) { @@ -60,14 +60,14 @@ export default class ReviewCommentView extends React.Component { className="github-Review-editCommentCancelButton btn" title="Cancel editing comment" disabled={this.props.isPosting} - onClick={() => this.onCancel(buffer.getText())}> + onClick={() => this.onCancel(buffer.getText() || '')}> Cancel @@ -139,10 +139,21 @@ export default class ReviewCommentView extends React.Component { message: 'Are you sure you want to discard your unsaved changes?', buttons: ['OK', 'Cancel'], }); - if (choice === 0) { this.setState({editing: false}); } + if (choice === 0) { + this.setState({editing: false}); + } } } + onSubmitUpdate = text => { + if (text === this.props.comment.body || text === '') { + this.setState({editing: false}); + return; + } + const didUpdateComment = () => this.setState({editing: false}); + this.props.updateComment(this.props.comment.id, text, didUpdateComment); + } + showActionsMenu = (event, comment, author) => { event.preventDefault(); diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index ececaed158..04de31ec3e 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -96,7 +96,7 @@ export default class ReviewsView extends React.Component { resolveThread: PropTypes.func.isRequired, unresolveThread: PropTypes.func.isRequired, addSingleComment: PropTypes.func.isRequired, - editComment: PropTypes.func.isRequired, + updateComment: PropTypes.func.isRequired, reportMutationErrors: PropTypes.func.isRequired, } @@ -474,6 +474,7 @@ export default class ReviewsView extends React.Component { renderAuthorAssociation={this.renderAuthorAssociation} isPosting={isPosting} confirm={this.props.confirm} + updateComment={this.props.updateComment} /> ); })} From 79e90777585ab76d8f9acb54bc4c662a54b08354 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 17:12:30 -0400 Subject: [PATCH 50/90] do the mutation --- lib/controllers/reviews-controller.js | 13 +- .../updatePrReviewCommentMutation.graphql.js | 129 ++++++++++++++++++ lib/mutations/update-pr-review-comment.js | 59 ++++++++ 3 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js create mode 100644 lib/mutations/update-pr-review-comment.js diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 63252bf94d..4ff09de134 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -11,6 +11,7 @@ import submitReviewMutation from '../mutations/submit-pr-review'; import deleteReviewMutation from '../mutations/delete-pr-review'; import resolveReviewThreadMutation from '../mutations/resolve-review-thread'; import unresolveReviewThreadMutation from '../mutations/unresolve-review-thread'; +import updatePrReviewCommentMutation from '../mutations/update-pr-review-comment'; import IssueishDetailItem from '../items/issueish-detail-item'; import {addEvent} from '../reporter-proxy'; @@ -345,8 +346,16 @@ export class BareReviewsController extends React.Component { } } - updateComment = (commentId, commentBody, callback) => { - + updateComment = async (commentId, commentBody, callback) => { + try { + await updatePrReviewCommentMutation(this.props.relay.environment, { + commentId, + commentBody, + }); + callback(); + } catch (error) { + this.props.reportMutationErrors('Unable to update comment', error); + } } } diff --git a/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js new file mode 100644 index 0000000000..06e759b314 --- /dev/null +++ b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js @@ -0,0 +1,129 @@ +/** + * @flow + * @relayHash 3d3a170f4f0ba10eaa8eae74bcc57f9d + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { ConcreteRequest } from 'relay-runtime'; +export type UpdatePullRequestReviewCommentInput = {| + pullRequestReviewCommentId: string, + body: string, + clientMutationId?: ?string, +|}; +export type updatePrReviewCommentMutationVariables = {| + input: UpdatePullRequestReviewCommentInput +|}; +export type updatePrReviewCommentMutationResponse = {| + +updatePullRequestReviewComment: ?{| + +pullRequestReviewComment: ?{| + +id: string, + +body: string, + |} + |} +|}; +export type updatePrReviewCommentMutation = {| + variables: updatePrReviewCommentMutationVariables, + response: updatePrReviewCommentMutationResponse, +|}; +*/ + + +/* +mutation updatePrReviewCommentMutation( + $input: UpdatePullRequestReviewCommentInput! +) { + updatePullRequestReviewComment(input: $input) { + pullRequestReviewComment { + id + body + } + } +} +*/ + +const node/*: ConcreteRequest*/ = (function(){ +var v0 = [ + { + "kind": "LocalArgument", + "name": "input", + "type": "UpdatePullRequestReviewCommentInput!", + "defaultValue": null + } +], +v1 = [ + { + "kind": "LinkedField", + "alias": null, + "name": "updatePullRequestReviewComment", + "storageKey": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input", + "type": "UpdatePullRequestReviewCommentInput!" + } + ], + "concreteType": "UpdatePullRequestReviewCommentPayload", + "plural": false, + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "name": "pullRequestReviewComment", + "storageKey": null, + "args": null, + "concreteType": "PullRequestReviewComment", + "plural": false, + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "name": "id", + "args": null, + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "name": "body", + "args": null, + "storageKey": null + } + ] + } + ] + } +]; +return { + "kind": "Request", + "fragment": { + "kind": "Fragment", + "name": "updatePrReviewCommentMutation", + "type": "Mutation", + "metadata": null, + "argumentDefinitions": (v0/*: any*/), + "selections": (v1/*: any*/) + }, + "operation": { + "kind": "Operation", + "name": "updatePrReviewCommentMutation", + "argumentDefinitions": (v0/*: any*/), + "selections": (v1/*: any*/) + }, + "params": { + "operationKind": "mutation", + "name": "updatePrReviewCommentMutation", + "id": null, + "text": "mutation updatePrReviewCommentMutation(\n $input: UpdatePullRequestReviewCommentInput!\n) {\n updatePullRequestReviewComment(input: $input) {\n pullRequestReviewComment {\n id\n body\n }\n }\n}\n", + "metadata": {} + } +}; +})(); +// prettier-ignore +(node/*: any*/).hash = '95910154c5572a47306db28dd5c6ce24'; +module.exports = node; diff --git a/lib/mutations/update-pr-review-comment.js b/lib/mutations/update-pr-review-comment.js new file mode 100644 index 0000000000..7f13962d75 --- /dev/null +++ b/lib/mutations/update-pr-review-comment.js @@ -0,0 +1,59 @@ +/* istanbul ignore file */ + +import {commitMutation, graphql} from 'react-relay'; + +const mutation = graphql` + mutation updatePrReviewCommentMutation($input: UpdatePullRequestReviewCommentInput!) { + updatePullRequestReviewComment(input: $input) { + pullRequestReviewComment { + id + body + } + } + } +`; + +export default (environment, {commentId, commentBody}) => { + const variables = { + input: { + pullRequestReviewCommentId: commentId, + body: commentBody, + }, + }; + + const optimisticResponse = { + updatePullRequestReviewComment: { + pullRequestReviewComment: { + id: commentId, + body: commentBody, + }, + }, + }; + // + // function optimisticUpdater(store) { + // const subject = store.get(commentId); + // console.log(subject); + // // const reactionGroups = subject.getLinkedRecords('reactionGroups') || []; + // // const reactionGroup = reactionGroups.find(group => group.getValue('content') === content); + // // if (!reactionGroup) { + // // return; + // // } + // // + // // reactionGroup.setValue(false, 'viewerHasReacted'); + // // const conn = reactionGroup.getLinkedRecord('users'); + // // conn.setValue(conn.getValue('totalCount') - 1, 'totalCount'); + // } + + return new Promise((resolve, reject) => { + commitMutation( + environment, + { + mutation, + variables, + optimisticResponse, + onCompleted: resolve, + onError: reject, + }, + ); + }); +}; From 21d0e0c60611edeb4668b6d79c9053306bc6f638 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 17:27:40 -0400 Subject: [PATCH 51/90] optimistically update comment body --- .../updatePrReviewCommentMutation.graphql.js | 15 ++++++++++++--- lib/mutations/update-pr-review-comment.js | 16 ++-------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js index 06e759b314..94a7defb42 100644 --- a/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js +++ b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 3d3a170f4f0ba10eaa8eae74bcc57f9d + * @relayHash b74d1504cf5b0d4b81427069c26301e3 */ /* eslint-disable */ @@ -22,6 +22,7 @@ export type updatePrReviewCommentMutationResponse = {| +pullRequestReviewComment: ?{| +id: string, +body: string, + +bodyHTML: any, |} |} |}; @@ -40,6 +41,7 @@ mutation updatePrReviewCommentMutation( pullRequestReviewComment { id body + bodyHTML } } } @@ -93,6 +95,13 @@ v1 = [ "name": "body", "args": null, "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "name": "bodyHTML", + "args": null, + "storageKey": null } ] } @@ -119,11 +128,11 @@ return { "operationKind": "mutation", "name": "updatePrReviewCommentMutation", "id": null, - "text": "mutation updatePrReviewCommentMutation(\n $input: UpdatePullRequestReviewCommentInput!\n) {\n updatePullRequestReviewComment(input: $input) {\n pullRequestReviewComment {\n id\n body\n }\n }\n}\n", + "text": "mutation updatePrReviewCommentMutation(\n $input: UpdatePullRequestReviewCommentInput!\n) {\n updatePullRequestReviewComment(input: $input) {\n pullRequestReviewComment {\n id\n body\n bodyHTML\n }\n }\n}\n", "metadata": {} } }; })(); // prettier-ignore -(node/*: any*/).hash = '95910154c5572a47306db28dd5c6ce24'; +(node/*: any*/).hash = '78e7d083f1783b40873971e9a73c8b0c'; module.exports = node; diff --git a/lib/mutations/update-pr-review-comment.js b/lib/mutations/update-pr-review-comment.js index 7f13962d75..e9687862df 100644 --- a/lib/mutations/update-pr-review-comment.js +++ b/lib/mutations/update-pr-review-comment.js @@ -1,6 +1,7 @@ /* istanbul ignore file */ import {commitMutation, graphql} from 'react-relay'; +import marked from 'marked'; const mutation = graphql` mutation updatePrReviewCommentMutation($input: UpdatePullRequestReviewCommentInput!) { @@ -8,6 +9,7 @@ const mutation = graphql` pullRequestReviewComment { id body + bodyHTML } } } @@ -29,20 +31,6 @@ export default (environment, {commentId, commentBody}) => { }, }, }; - // - // function optimisticUpdater(store) { - // const subject = store.get(commentId); - // console.log(subject); - // // const reactionGroups = subject.getLinkedRecords('reactionGroups') || []; - // // const reactionGroup = reactionGroups.find(group => group.getValue('content') === content); - // // if (!reactionGroup) { - // // return; - // // } - // // - // // reactionGroup.setValue(false, 'viewerHasReacted'); - // // const conn = reactionGroup.getLinkedRecord('users'); - // // conn.setValue(conn.getValue('totalCount') - 1, 'totalCount'); - // } return new Promise((resolve, reject) => { commitMutation( From 9269a852ad8974baeaebb8dbadac34e43ca74917 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 17:28:01 -0400 Subject: [PATCH 52/90] but actaully parse the comment from markdown to html first --- lib/mutations/update-pr-review-comment.js | 1 + package-lock.json | 5 +++++ package.json | 1 + 3 files changed, 7 insertions(+) diff --git a/lib/mutations/update-pr-review-comment.js b/lib/mutations/update-pr-review-comment.js index e9687862df..407bb47fda 100644 --- a/lib/mutations/update-pr-review-comment.js +++ b/lib/mutations/update-pr-review-comment.js @@ -28,6 +28,7 @@ export default (environment, {commentId, commentBody}) => { pullRequestReviewComment: { id: commentId, body: commentBody, + bodyHTML: marked(commentBody, {gfm: true}), }, }, }; diff --git a/package-lock.json b/package-lock.json index b0ebaaf7f9..a9b5b1b8a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5140,6 +5140,11 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.2.tgz", + "integrity": "sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA==" + }, "md5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", diff --git a/package.json b/package.json index f17e3ef237..32479d2bc3 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "graphql": "14.2.1", "keytar": "4.4.1", "lodash.memoize": "4.1.2", + "marked": "^0.6.2", "moment": "2.24.0", "node-emoji": "1.10.0", "prop-types": "15.7.2", From f41c9e4bc38d8744fa4a0c3508e4ca3f0542d43a Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 17:48:36 -0400 Subject: [PATCH 53/90] fix button margin --- styles/review.less | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/styles/review.less b/styles/review.less index 9f3ea9eabd..c4a78396a5 100644 --- a/styles/review.less +++ b/styles/review.less @@ -416,6 +416,10 @@ color: @text-color-subtle; } + &-actionsMenu::before { + margin-right: 0; + } + &-pendingBadge { margin-left: @component-padding; } @@ -462,7 +466,7 @@ margin: @component-padding/2 0 @component-padding 0; display: flex; justify-content: flex-end; - + .btn { margin-left: @component-padding/2; } From 2dfa2577da7fe0335f195a5b4faaaa34cff61a53 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 21:03:54 -0400 Subject: [PATCH 54/90] refractor out the comment editor to a reusable component --- lib/views/editable-review.js | 134 +++++++++++++++++++++++++++++++ lib/views/review-comment-view.js | 125 +++------------------------- 2 files changed, 146 insertions(+), 113 deletions(-) create mode 100644 lib/views/editable-review.js diff --git a/lib/views/editable-review.js b/lib/views/editable-review.js new file mode 100644 index 0000000000..d148ec6e4d --- /dev/null +++ b/lib/views/editable-review.js @@ -0,0 +1,134 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cx from 'classnames'; +import {remote, shell} from 'electron'; +import {TextBuffer} from 'atom'; +import AtomTextEditor from '../atom/atom-text-editor'; +import RefHolder from '../models/ref-holder'; +import {addEvent} from '../reporter-proxy'; + +const {Menu, MenuItem} = remote; + +export default class EditableReview extends React.Component { + static propTypes = { + originalContent: PropTypes.object.isRequired, + isPosting: PropTypes.bool.isRequired, + confirm: PropTypes.func.isRequired, + updateComment: PropTypes.func.isRequired, + render: PropTypes.func.isRequired, + } + + constructor(props) { + super(props); + this.refEditor = new RefHolder(); + this.state = {editing: false}; + } + + render() { + return this.state.editing ? this.renderEditor() : this.props.render(this.showActionsMenu); + } + + renderEditor() { + const buffer = new TextBuffer(); + buffer.setText(this.props.originalContent.body); + + return ( +
+ +
+ + +
+
+ ); + } + + onCancel = text => { + if (text === this.props.originalContent.body) { + this.setState({editing: false}); + } else { + const choice = this.props.confirm({ + message: 'Are you sure you want to discard your unsaved changes?', + buttons: ['OK', 'Cancel'], + }); + if (choice === 0) { + this.setState({editing: false}); + } + } + } + + onSubmitUpdate = text => { + if (text === this.props.originalContent.body || text === '') { + this.setState({editing: false}); + return; + } + const didUpdateComment = () => this.setState({editing: false}); + this.props.updateComment(this.props.originalContent.id, text, didUpdateComment); + } + + reportAbuse = (commentUrl, author) => { + return new Promise((resolve, reject) => { + const url = 'https://github.com/contact/report-content?report=' + + `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('report-abuse', {package: 'github', component: this.constructor.name}); + } + }); + }); + } + + openOnGitHub = url => { + return new Promise((resolve, reject) => { + shell.openExternal(url, {}, err => { + if (err) { reject(err); } else { + resolve(); + addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); + } + }); + }); + } + + showActionsMenu = (event, comment, author) => { + event.preventDefault(); + + const menu = new Menu(); + + menu.append(new MenuItem({ + label: 'Edit', + click: () => this.setState({editing: true}), + })); + + menu.append(new MenuItem({ + label: 'Open on GitHub', + click: () => this.openOnGitHub(comment.url), + })); + + menu.append(new MenuItem({ + label: 'Report abuse', + click: () => this.reportAbuse(comment.url, author.login), + })); + + menu.popup(remote.getCurrentWindow()); + } +} diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index fab4ce0ffe..eaf4b6598d 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -1,25 +1,21 @@ import React from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; -import {remote, shell} from 'electron'; -const {Menu, MenuItem} = remote; -import {TextBuffer} from 'atom'; - import Timeago from './timeago'; import Octicon from '../atom/octicon'; -import AtomTextEditor from '../atom/atom-text-editor'; import GithubDotcomMarkdown from './github-dotcom-markdown'; import EmojiReactionsController from '../controllers/emoji-reactions-controller'; import {GHOST_USER} from '../helpers'; -import {addEvent} from '../reporter-proxy'; import RefHolder from '../models/ref-holder'; +import EditableReview from './editable-review'; + export default class ReviewCommentView extends React.Component { static propTypes = { comment: PropTypes.object.isRequired, isPosting: PropTypes.bool.isRequired, - confirm: PropTypes.object.isRequired, + confirm: PropTypes.func.isRequired, tooltips: PropTypes.object.isRequired, renderEditedLink: PropTypes.func.isRequired, renderAuthorAssociation: PropTypes.func.isRequired, @@ -38,44 +34,17 @@ export default class ReviewCommentView extends React.Component { } render() { - return this.state.editing ? this.renderEditor() : this.renderComment(); - } - - renderEditor() { - const buffer = new TextBuffer(); - buffer.setText(this.props.comment.body); - return ( -
- -
- - -
-
- ); + ); } - renderComment() { + renderComment = showActionsMenu => { const comment = this.props.comment; if (comment.isMinimized) { @@ -112,7 +81,7 @@ export default class ReviewCommentView extends React.Component { this.showActionsMenu(event, comment, author)} + onClick={event => showActionsMenu(event, comment, author)} />
@@ -131,74 +100,4 @@ export default class ReviewCommentView extends React.Component { ); } - onCancel = text => { - if (text === this.props.comment.body) { - this.setState({editing: false}); - } else { - const choice = this.props.confirm({ - message: 'Are you sure you want to discard your unsaved changes?', - buttons: ['OK', 'Cancel'], - }); - if (choice === 0) { - this.setState({editing: false}); - } - } - } - - onSubmitUpdate = text => { - if (text === this.props.comment.body || text === '') { - this.setState({editing: false}); - return; - } - const didUpdateComment = () => this.setState({editing: false}); - this.props.updateComment(this.props.comment.id, text, didUpdateComment); - } - - showActionsMenu = (event, comment, author) => { - event.preventDefault(); - - const menu = new Menu(); - - menu.append(new MenuItem({ - label: 'Edit', - click: () => this.setState({editing: true}), - })); - - menu.append(new MenuItem({ - label: 'Open on GitHub', - click: () => this.openOnGitHub(comment.url), - })); - - menu.append(new MenuItem({ - label: 'Report abuse', - click: () => this.reportAbuse(comment.url, author.login), - })); - - menu.popup(remote.getCurrentWindow()); - } - - - reportAbuse = (commentUrl, author) => { - return new Promise((resolve, reject) => { - const url = 'https://github.com/contact/report-content?report=' + - `${encodeURIComponent(author)}&content_url=${encodeURIComponent(commentUrl)}`; - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('report-abuse', {package: 'github', component: this.constructor.name}); - } - }); - }); - } - - openOnGitHub = url => { - return new Promise((resolve, reject) => { - shell.openExternal(url, {}, err => { - if (err) { reject(err); } else { - resolve(); - addEvent('open-comment-in-browser', {package: 'github', component: this.constructor.name}); - } - }); - }); - } } From 7706a8d26a6f24033c20d18ef950d33986d830df Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 21:06:55 -0400 Subject: [PATCH 55/90] naming is hard --- lib/views/{editable-review.js => actionable-review-view.js} | 2 +- lib/views/review-comment-view.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/views/{editable-review.js => actionable-review-view.js} (98%) diff --git a/lib/views/editable-review.js b/lib/views/actionable-review-view.js similarity index 98% rename from lib/views/editable-review.js rename to lib/views/actionable-review-view.js index d148ec6e4d..b3da8aae50 100644 --- a/lib/views/editable-review.js +++ b/lib/views/actionable-review-view.js @@ -9,7 +9,7 @@ import {addEvent} from '../reporter-proxy'; const {Menu, MenuItem} = remote; -export default class EditableReview extends React.Component { +export default class ActionableReviewView extends React.Component { static propTypes = { originalContent: PropTypes.object.isRequired, isPosting: PropTypes.bool.isRequired, diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index eaf4b6598d..fee424a6b6 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -9,7 +9,7 @@ import EmojiReactionsController from '../controllers/emoji-reactions-controller' import {GHOST_USER} from '../helpers'; import RefHolder from '../models/ref-holder'; -import EditableReview from './editable-review'; +import ActionableReviewView from './actionable-review-view'; export default class ReviewCommentView extends React.Component { static propTypes = { @@ -35,7 +35,7 @@ export default class ReviewCommentView extends React.Component { render() { return ( - Date: Wed, 8 May 2019 22:11:21 -0400 Subject: [PATCH 56/90] some clean up --- lib/views/actionable-review-view.js | 4 ++-- lib/views/review-comment-view.js | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index b3da8aae50..6bea03fdf9 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -14,7 +14,7 @@ export default class ActionableReviewView extends React.Component { originalContent: PropTypes.object.isRequired, isPosting: PropTypes.bool.isRequired, confirm: PropTypes.func.isRequired, - updateComment: PropTypes.func.isRequired, + contentUpdater: PropTypes.func.isRequired, render: PropTypes.func.isRequired, } @@ -82,7 +82,7 @@ export default class ActionableReviewView extends React.Component { return; } const didUpdateComment = () => this.setState({editing: false}); - this.props.updateComment(this.props.originalContent.id, text, didUpdateComment); + this.props.contentUpdater(this.props.originalContent.id, text, didUpdateComment); } reportAbuse = (commentUrl, author) => { diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index fee424a6b6..08b273f002 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -27,10 +27,7 @@ export default class ReviewCommentView extends React.Component { constructor(props) { super(props); - this.refEditor = new RefHolder(); - - this.state = {editing: false}; } render() { @@ -39,7 +36,7 @@ export default class ReviewCommentView extends React.Component { originalContent={this.props.comment} isPosting={this.props.isPosting} confirm={this.props.confirm} - updateComment={this.props.updateComment} + contentUpdater={this.props.updateComment} render={this.renderComment} />); } From 5462fc1e170fc4b09afe3f423b4a44847fb41769 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Wed, 8 May 2019 22:19:52 -0400 Subject: [PATCH 57/90] use smaller buttons --- lib/views/actionable-review-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 6bea03fdf9..0bff60e8ec 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -44,14 +44,14 @@ export default class ActionableReviewView extends React.Component { />
+
+ ); + }} + /> +
); } diff --git a/styles/review.less b/styles/review.less index c4a78396a5..86d3744724 100644 --- a/styles/review.less +++ b/styles/review.less @@ -15,6 +15,13 @@ overflow-y: hidden; height: 100%; + atom-text-editor { + padding: @component-padding/2; + border-top: 1px solid @base-border-color; + border-bottom: 1px solid @base-border-color; + border-radius: @component-border-radius; + } + // Top Header ------------------------------------------ &-topHeader { @@ -333,12 +340,6 @@ // Diff ------------------ - atom-text-editor { - padding: @component-padding/2; - border-top: 1px solid @base-border-color; - border-bottom: 1px solid @base-border-color; - } - &-diffLine { padding: 0 @component-padding/2; line-height: 1.75; @@ -418,6 +419,7 @@ &-actionsMenu::before { margin-right: 0; + margin-left: @component-padding/2; } &-pendingBadge { @@ -436,7 +438,7 @@ } } - &-reply, &-editComment { + &-reply, &-editable { margin-top: @component-padding; atom-text-editor { @@ -462,7 +464,7 @@ padding: 0 2*@component-padding; } - &-editComment-footer { + &-editable-footer { margin: @component-padding/2 0 @component-padding 0; display: flex; justify-content: flex-end; From a7efd8417e172589b693cc2fb664e56acc64cd1c Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 9 May 2019 13:40:57 -0400 Subject: [PATCH 61/90] add update review summary mutation --- .../updatePrReviewSummaryMutation.graphql.js | 138 ++++++++++++++++++ lib/mutations/update-pr-review-summary.js | 48 ++++++ 2 files changed, 186 insertions(+) create mode 100644 lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js create mode 100644 lib/mutations/update-pr-review-summary.js diff --git a/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js b/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js new file mode 100644 index 0000000000..af7996cd76 --- /dev/null +++ b/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js @@ -0,0 +1,138 @@ +/** + * @flow + * @relayHash 6f60db0700812e37c5c5f835b64af67f + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { ConcreteRequest } from 'relay-runtime'; +export type UpdatePullRequestReviewInput = {| + pullRequestReviewId: string, + body: string, + clientMutationId?: ?string, +|}; +export type updatePrReviewSummaryMutationVariables = {| + input: UpdatePullRequestReviewInput +|}; +export type updatePrReviewSummaryMutationResponse = {| + +updatePullRequestReview: ?{| + +pullRequestReview: ?{| + +id: string, + +body: string, + +bodyHTML: any, + |} + |} +|}; +export type updatePrReviewSummaryMutation = {| + variables: updatePrReviewSummaryMutationVariables, + response: updatePrReviewSummaryMutationResponse, +|}; +*/ + + +/* +mutation updatePrReviewSummaryMutation( + $input: UpdatePullRequestReviewInput! +) { + updatePullRequestReview(input: $input) { + pullRequestReview { + id + body + bodyHTML + } + } +} +*/ + +const node/*: ConcreteRequest*/ = (function(){ +var v0 = [ + { + "kind": "LocalArgument", + "name": "input", + "type": "UpdatePullRequestReviewInput!", + "defaultValue": null + } +], +v1 = [ + { + "kind": "LinkedField", + "alias": null, + "name": "updatePullRequestReview", + "storageKey": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input", + "type": "UpdatePullRequestReviewInput!" + } + ], + "concreteType": "UpdatePullRequestReviewPayload", + "plural": false, + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "name": "pullRequestReview", + "storageKey": null, + "args": null, + "concreteType": "PullRequestReview", + "plural": false, + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "name": "id", + "args": null, + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "name": "body", + "args": null, + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "name": "bodyHTML", + "args": null, + "storageKey": null + } + ] + } + ] + } +]; +return { + "kind": "Request", + "fragment": { + "kind": "Fragment", + "name": "updatePrReviewSummaryMutation", + "type": "Mutation", + "metadata": null, + "argumentDefinitions": (v0/*: any*/), + "selections": (v1/*: any*/) + }, + "operation": { + "kind": "Operation", + "name": "updatePrReviewSummaryMutation", + "argumentDefinitions": (v0/*: any*/), + "selections": (v1/*: any*/) + }, + "params": { + "operationKind": "mutation", + "name": "updatePrReviewSummaryMutation", + "id": null, + "text": "mutation updatePrReviewSummaryMutation(\n $input: UpdatePullRequestReviewInput!\n) {\n updatePullRequestReview(input: $input) {\n pullRequestReview {\n id\n body\n bodyHTML\n }\n }\n}\n", + "metadata": {} + } +}; +})(); +// prettier-ignore +(node/*: any*/).hash = 'e8da32c47a4d30e206902f1fe4aa4607'; +module.exports = node; diff --git a/lib/mutations/update-pr-review-summary.js b/lib/mutations/update-pr-review-summary.js new file mode 100644 index 0000000000..e5a6ef8955 --- /dev/null +++ b/lib/mutations/update-pr-review-summary.js @@ -0,0 +1,48 @@ +/* istanbul ignore file */ + +import {commitMutation, graphql} from 'react-relay'; +import marked from 'marked'; + +const mutation = graphql` + mutation updatePrReviewSummaryMutation($input: UpdatePullRequestReviewInput!) { + updatePullRequestReview(input: $input) { + pullRequestReview { + id + body + bodyHTML + } + } + } +`; + +export default (environment, {summaryId, summaryBody}) => { + const variables = { + input: { + pullRequestReviewCommentId: summaryId, + body: summaryBody, + }, + }; + + const optimisticResponse = { + updatePullRequestReview: { + pullRequestReview: { + id: summaryId, + body: summaryBody, + bodyHTML: marked(summaryBody, {gfm: true}), + }, + }, + }; + + return new Promise((resolve, reject) => { + commitMutation( + environment, + { + mutation, + variables, + optimisticResponse, + onCompleted: resolve, + onError: reject, + }, + ); + }); +}; From c866360667fbc95df9b997d0ddd888e0cb210bda Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 9 May 2019 13:55:50 -0400 Subject: [PATCH 62/90] actually hook up the mutation with UI --- lib/controllers/reviews-controller.js | 14 ++++++++++++++ lib/mutations/update-pr-review-summary.js | 12 ++++++------ lib/views/reviews-view.js | 3 ++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 4ff09de134..99413717fd 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -12,6 +12,7 @@ import deleteReviewMutation from '../mutations/delete-pr-review'; import resolveReviewThreadMutation from '../mutations/resolve-review-thread'; import unresolveReviewThreadMutation from '../mutations/unresolve-review-thread'; import updatePrReviewCommentMutation from '../mutations/update-pr-review-comment'; +import updatePrReviewSummaryMutation from '../mutations/update-pr-review-summary'; import IssueishDetailItem from '../items/issueish-detail-item'; import {addEvent} from '../reporter-proxy'; @@ -147,6 +148,7 @@ export class BareReviewsController extends React.Component { unresolveThread={this.unresolveThread} addSingleComment={this.addSingleComment} updateComment={this.updateComment} + updateSummary={this.updateSummary} {...this.props} /> )} @@ -357,6 +359,18 @@ export class BareReviewsController extends React.Component { this.props.reportMutationErrors('Unable to update comment', error); } } + + updateSummary = async (reviewId, reviewBody, callback) => { + try { + await updatePrReviewSummaryMutation(this.props.relay.environment, { + reviewId, + reviewBody, + }); + callback(); + } catch (error) { + this.props.reportMutationErrors('Unable to update review summary', error); + } + } } export default createFragmentContainer(BareReviewsController, { diff --git a/lib/mutations/update-pr-review-summary.js b/lib/mutations/update-pr-review-summary.js index e5a6ef8955..990cc980b1 100644 --- a/lib/mutations/update-pr-review-summary.js +++ b/lib/mutations/update-pr-review-summary.js @@ -15,20 +15,20 @@ const mutation = graphql` } `; -export default (environment, {summaryId, summaryBody}) => { +export default (environment, {reviewId, reviewBody}) => { const variables = { input: { - pullRequestReviewCommentId: summaryId, - body: summaryBody, + pullRequestReviewId: reviewId, + body: reviewBody, }, }; const optimisticResponse = { updatePullRequestReview: { pullRequestReview: { - id: summaryId, - body: summaryBody, - bodyHTML: marked(summaryBody, {gfm: true}), + id: reviewId, + body: reviewBody, + bodyHTML: marked(reviewBody, {gfm: true}), }, }, }; diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index cd548410fe..19e08ed2ef 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -99,6 +99,7 @@ export default class ReviewsView extends React.Component { unresolveThread: PropTypes.func.isRequired, addSingleComment: PropTypes.func.isRequired, updateComment: PropTypes.func.isRequired, + updateSummary: PropTypes.func.isRequired, reportMutationErrors: PropTypes.func.isRequired, } @@ -272,7 +273,7 @@ export default class ReviewsView extends React.Component { {}} + contentUpdater={this.props.updateSummary} render={showActionsMenu => { return ( From fc046ad6c576e4df82eba30b6af154a1d19d50d5 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 9 May 2019 13:58:41 -0400 Subject: [PATCH 63/90] add some metrics tings :sparkles: --- lib/controllers/reviews-controller.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 99413717fd..6c8f5e5aa6 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -354,6 +354,7 @@ export class BareReviewsController extends React.Component { commentId, commentBody, }); + addEvent('update-review-comment', {package: 'github'}); callback(); } catch (error) { this.props.reportMutationErrors('Unable to update comment', error); @@ -366,6 +367,7 @@ export class BareReviewsController extends React.Component { reviewId, reviewBody, }); + addEvent('update-review-summary', {package: 'github'}); callback(); } catch (error) { this.props.reportMutationErrors('Unable to update review summary', error); From 15af3b8c3558f01248011b5d3af7d436cf74a5cc Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 9 May 2019 16:29:22 -0400 Subject: [PATCH 64/90] query for `viewerCanUpdate` also so we know whether to show the edit action for a particular comment/review summary or not --- ...tedReviewsContainerRefetchQuery.graphql.js | 35 ++- ...ommentDecorationsContainerQuery.graphql.js | 35 ++- .../issueishDetailContainerQuery.graphql.js | 219 +++++++++--------- .../reviewsContainerQuery.graphql.js | 35 ++- .../reviewCommentsAccumulatorQuery.graphql.js | 12 +- ...ommentsAccumulator_reviewThread.graphql.js | 10 +- ...reviewSummariesAccumulatorQuery.graphql.js | 12 +- ...ummariesAccumulator_pullRequest.graphql.js | 22 +- .../reviewThreadsAccumulatorQuery.graphql.js | 12 +- .../review-comments-accumulator.js | 1 + .../review-summaries-accumulator.js | 1 + 11 files changed, 240 insertions(+), 154 deletions(-) diff --git a/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js b/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js index b45b5bdc0f..d263535af8 100644 --- a/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js +++ b/lib/containers/__generated__/aggregatedReviewsContainerRefetchQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash c0f651fb76f956610d944bcbeb62621f + * @relayHash 8ba50287839e4a5fa5c1e882deaa661a */ /* eslint-disable */ @@ -98,6 +98,7 @@ fragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest { id } } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable __typename @@ -156,6 +157,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -352,11 +354,18 @@ v13 = { v14 = { "kind": "ScalarField", "alias": null, - "name": "authorAssociation", + "name": "viewerCanUpdate", "args": null, "storageKey": null }, v15 = { + "kind": "ScalarField", + "alias": null, + "name": "authorAssociation", + "args": null, + "storageKey": null +}, +v16 = { "kind": "LinkedField", "alias": null, "name": "reactionGroups", @@ -399,14 +408,14 @@ v15 = { } ] }, -v16 = { +v17 = { "kind": "ScalarField", "alias": null, "name": "viewerCanReact", "args": null, "storageKey": null }, -v17 = [ +v18 = [ { "kind": "Variable", "name": "after", @@ -420,7 +429,7 @@ v17 = [ "type": "Int" } ], -v18 = [ +v19 = [ { "kind": "Variable", "name": "after", @@ -640,6 +649,7 @@ return { (v14/*: any*/), (v15/*: any*/), (v16/*: any*/), + (v17/*: any*/), (v2/*: any*/) ] } @@ -661,7 +671,7 @@ return { "alias": null, "name": "reviewThreads", "storageKey": null, - "args": (v17/*: any*/), + "args": (v18/*: any*/), "concreteType": "PullRequestReviewThreadConnection", "plural": false, "selections": [ @@ -725,7 +735,7 @@ return { "alias": null, "name": "comments", "storageKey": null, - "args": (v18/*: any*/), + "args": (v19/*: any*/), "concreteType": "PullRequestReviewCommentConnection", "plural": false, "selections": [ @@ -767,7 +777,8 @@ return { "storageKey": null }, (v10/*: any*/), - (v16/*: any*/), + (v17/*: any*/), + (v14/*: any*/), { "kind": "LinkedField", "alias": null, @@ -800,8 +811,8 @@ return { }, (v11/*: any*/), (v4/*: any*/), - (v14/*: any*/), (v15/*: any*/), + (v16/*: any*/), (v2/*: any*/) ] } @@ -813,7 +824,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "comments", - "args": (v18/*: any*/), + "args": (v19/*: any*/), "handle": "connection", "key": "ReviewCommentsAccumulator_comments", "filters": null @@ -829,7 +840,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "reviewThreads", - "args": (v17/*: any*/), + "args": (v18/*: any*/), "handle": "connection", "key": "ReviewThreadsAccumulator_reviewThreads", "filters": null @@ -844,7 +855,7 @@ return { "operationKind": "query", "name": "aggregatedReviewsContainerRefetchQuery", "id": null, - "text": "query aggregatedReviewsContainerRefetchQuery(\n $prId: ID!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n pullRequest: node(id: $prId) {\n __typename\n ...prCheckoutController_pullRequest\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query aggregatedReviewsContainerRefetchQuery(\n $prId: ID!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n pullRequest: node(id: $prId) {\n __typename\n ...prCheckoutController_pullRequest\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n viewerCanUpdate\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js b/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js index edf4bd81ab..005dfe1cbd 100644 --- a/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js +++ b/lib/containers/__generated__/commentDecorationsContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 742d89b5868af5d979919f227b8d325e + * @relayHash dd01fba0da8ae082c8dda29a05109406 */ /* eslint-disable */ @@ -131,6 +131,7 @@ fragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest { id } } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable __typename @@ -189,6 +190,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -478,11 +480,18 @@ v19 = { v20 = { "kind": "ScalarField", "alias": null, - "name": "authorAssociation", + "name": "viewerCanUpdate", "args": null, "storageKey": null }, v21 = { + "kind": "ScalarField", + "alias": null, + "name": "authorAssociation", + "args": null, + "storageKey": null +}, +v22 = { "kind": "LinkedField", "alias": null, "name": "reactionGroups", @@ -519,14 +528,14 @@ v21 = { } ] }, -v22 = { +v23 = { "kind": "ScalarField", "alias": null, "name": "viewerCanReact", "args": null, "storageKey": null }, -v23 = [ +v24 = [ { "kind": "Variable", "name": "after", @@ -540,7 +549,7 @@ v23 = [ "type": "Int" } ], -v24 = [ +v25 = [ { "kind": "Variable", "name": "after", @@ -793,6 +802,7 @@ return { (v20/*: any*/), (v21/*: any*/), (v22/*: any*/), + (v23/*: any*/), (v7/*: any*/) ] } @@ -814,7 +824,7 @@ return { "alias": null, "name": "reviewThreads", "storageKey": null, - "args": (v23/*: any*/), + "args": (v24/*: any*/), "concreteType": "PullRequestReviewThreadConnection", "plural": false, "selections": [ @@ -878,7 +888,7 @@ return { "alias": null, "name": "comments", "storageKey": null, - "args": (v24/*: any*/), + "args": (v25/*: any*/), "concreteType": "PullRequestReviewCommentConnection", "plural": false, "selections": [ @@ -920,7 +930,8 @@ return { "storageKey": null }, (v16/*: any*/), - (v22/*: any*/), + (v23/*: any*/), + (v20/*: any*/), { "kind": "LinkedField", "alias": null, @@ -953,8 +964,8 @@ return { }, (v17/*: any*/), (v11/*: any*/), - (v20/*: any*/), (v21/*: any*/), + (v22/*: any*/), (v7/*: any*/) ] } @@ -966,7 +977,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "comments", - "args": (v24/*: any*/), + "args": (v25/*: any*/), "handle": "connection", "key": "ReviewCommentsAccumulator_comments", "filters": null @@ -982,7 +993,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "reviewThreads", - "args": (v23/*: any*/), + "args": (v24/*: any*/), "handle": "connection", "key": "ReviewThreadsAccumulator_reviewThreads", "filters": null @@ -1003,7 +1014,7 @@ return { "operationKind": "query", "name": "commentDecorationsContainerQuery", "id": null, - "text": "query commentDecorationsContainerQuery(\n $headOwner: String!\n $headName: String!\n $headRef: String!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n $first: Int!\n) {\n repository(owner: $headOwner, name: $headName) {\n ref(qualifiedName: $headRef) {\n associatedPullRequests(first: $first, states: [OPEN]) {\n totalCount\n nodes {\n number\n headRefOid\n ...commentDecorationsController_pullRequests\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n }\n id\n }\n id\n }\n}\n\nfragment commentDecorationsController_pullRequests on PullRequest {\n number\n headRefName\n headRefOid\n headRepository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query commentDecorationsContainerQuery(\n $headOwner: String!\n $headName: String!\n $headRef: String!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n $first: Int!\n) {\n repository(owner: $headOwner, name: $headName) {\n ref(qualifiedName: $headRef) {\n associatedPullRequests(first: $first, states: [OPEN]) {\n totalCount\n nodes {\n number\n headRefOid\n ...commentDecorationsController_pullRequests\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n id\n }\n }\n id\n }\n id\n }\n}\n\nfragment commentDecorationsController_pullRequests on PullRequest {\n number\n headRefName\n headRefOid\n headRepository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n viewerCanUpdate\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js b/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js index c622d2b1f6..8d821ac00d 100644 --- a/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js +++ b/lib/containers/__generated__/issueishDetailContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash cc03ac4a2cc819e8cc15edf606b38e19 + * @relayHash d690502d1387caafdee18568d0567f77 */ /* eslint-disable */ @@ -574,6 +574,7 @@ fragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest { id } } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable __typename @@ -632,6 +633,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -877,13 +879,20 @@ v17 = { ] }, v18 = { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null +}, +v19 = { "kind": "ScalarField", "alias": null, "name": "authorAssociation", "args": null, "storageKey": null }, -v19 = [ +v20 = [ { "kind": "ScalarField", "alias": null, @@ -892,7 +901,7 @@ v19 = [ "storageKey": null } ], -v20 = { +v21 = { "kind": "LinkedField", "alias": null, "name": "reactionGroups", @@ -923,18 +932,18 @@ v20 = { "args": null, "concreteType": "ReactingUserConnection", "plural": false, - "selections": (v19/*: any*/) + "selections": (v20/*: any*/) } ] }, -v21 = { +v22 = { "kind": "ScalarField", "alias": null, "name": "viewerCanReact", "args": null, "storageKey": null }, -v22 = [ +v23 = [ { "kind": "Variable", "name": "after", @@ -948,11 +957,11 @@ v22 = [ "type": "Int" } ], -v23 = [ +v24 = [ (v15/*: any*/), (v4/*: any*/) ], -v24 = [ +v25 = [ { "kind": "Variable", "name": "after", @@ -966,40 +975,40 @@ v24 = [ "type": "Int" } ], -v25 = { +v26 = { "kind": "ScalarField", "alias": null, "name": "path", "args": null, "storageKey": null }, -v26 = { +v27 = { "kind": "ScalarField", "alias": null, "name": "position", "args": null, "storageKey": null }, -v27 = { +v28 = { "kind": "ScalarField", "alias": null, "name": "createdAt", "args": null, "storageKey": null }, -v28 = { +v29 = { "kind": "ScalarField", "alias": null, "name": "name", "args": null, "storageKey": null }, -v29 = [ +v30 = [ (v3/*: any*/), (v15/*: any*/), (v4/*: any*/) ], -v30 = { +v31 = { "kind": "LinkedField", "alias": null, "name": "owner", @@ -1007,23 +1016,23 @@ v30 = { "args": null, "concreteType": null, "plural": false, - "selections": (v29/*: any*/) + "selections": (v30/*: any*/) }, -v31 = { +v32 = { "kind": "ScalarField", "alias": null, "name": "title", "args": null, "storageKey": null }, -v32 = { +v33 = { "kind": "ScalarField", "alias": null, "name": "number", "args": null, "storageKey": null }, -v33 = [ +v34 = [ { "kind": "Variable", "name": "after", @@ -1037,7 +1046,7 @@ v33 = [ "type": "Int" } ], -v34 = { +v35 = { "kind": "LinkedField", "alias": null, "name": "pageInfo", @@ -1050,20 +1059,20 @@ v34 = { (v7/*: any*/) ] }, -v35 = { +v36 = { "kind": "ScalarField", "alias": null, "name": "isCrossRepository", "args": null, "storageKey": null }, -v36 = [ +v37 = [ (v3/*: any*/), (v15/*: any*/), (v16/*: any*/), (v4/*: any*/) ], -v37 = { +v38 = { "kind": "InlineFragment", "type": "CrossReferencedEvent", "selections": [ @@ -1074,7 +1083,7 @@ v37 = { "args": null, "storageKey": null }, - (v35/*: any*/), + (v36/*: any*/), { "kind": "LinkedField", "alias": null, @@ -1083,7 +1092,7 @@ v37 = { "args": null, "concreteType": null, "plural": false, - "selections": (v36/*: any*/) + "selections": (v37/*: any*/) }, { "kind": "LinkedField", @@ -1104,8 +1113,8 @@ v37 = { "concreteType": "Repository", "plural": false, "selections": [ - (v28/*: any*/), - (v30/*: any*/), + (v29/*: any*/), + (v31/*: any*/), (v4/*: any*/), { "kind": "ScalarField", @@ -1121,8 +1130,8 @@ v37 = { "kind": "InlineFragment", "type": "PullRequest", "selections": [ + (v33/*: any*/), (v32/*: any*/), - (v31/*: any*/), (v5/*: any*/), { "kind": "ScalarField", @@ -1137,8 +1146,8 @@ v37 = { "kind": "InlineFragment", "type": "Issue", "selections": [ + (v33/*: any*/), (v32/*: any*/), - (v31/*: any*/), (v5/*: any*/), { "kind": "ScalarField", @@ -1153,13 +1162,13 @@ v37 = { } ] }, -v38 = [ +v39 = [ (v3/*: any*/), (v16/*: any*/), (v15/*: any*/), (v4/*: any*/) ], -v39 = { +v40 = { "kind": "InlineFragment", "type": "IssueComment", "selections": [ @@ -1171,14 +1180,14 @@ v39 = { "args": null, "concreteType": null, "plural": false, - "selections": (v38/*: any*/) + "selections": (v39/*: any*/) }, (v11/*: any*/), - (v27/*: any*/), + (v28/*: any*/), (v5/*: any*/) ] }, -v40 = { +v41 = { "kind": "LinkedField", "alias": null, "name": "user", @@ -1186,16 +1195,16 @@ v40 = { "args": null, "concreteType": "User", "plural": false, - "selections": (v23/*: any*/) + "selections": (v24/*: any*/) }, -v41 = { +v42 = { "kind": "ScalarField", "alias": "sha", "name": "oid", "args": null, "storageKey": null }, -v42 = { +v43 = { "kind": "InlineFragment", "type": "Commit", "selections": [ @@ -1208,8 +1217,8 @@ v42 = { "concreteType": "GitActor", "plural": false, "selections": [ - (v28/*: any*/), - (v40/*: any*/), + (v29/*: any*/), + (v41/*: any*/), (v16/*: any*/) ] }, @@ -1222,9 +1231,9 @@ v42 = { "concreteType": "GitActor", "plural": false, "selections": [ - (v28/*: any*/), + (v29/*: any*/), (v16/*: any*/), - (v40/*: any*/) + (v41/*: any*/) ] }, { @@ -1234,7 +1243,7 @@ v42 = { "args": null, "storageKey": null }, - (v41/*: any*/), + (v42/*: any*/), { "kind": "ScalarField", "alias": null, @@ -1258,7 +1267,7 @@ v42 = { } ] }, -v43 = [ +v44 = [ { "kind": "Variable", "name": "after", @@ -1272,7 +1281,7 @@ v43 = [ "type": "Int" } ], -v44 = [ +v45 = [ { "kind": "ScalarField", "alias": null, @@ -1282,7 +1291,7 @@ v44 = [ }, (v4/*: any*/) ], -v45 = { +v46 = { "kind": "LinkedField", "alias": null, "name": "commit", @@ -1290,9 +1299,9 @@ v45 = { "args": null, "concreteType": "Commit", "plural": false, - "selections": (v44/*: any*/) + "selections": (v45/*: any*/) }, -v46 = { +v47 = { "kind": "LinkedField", "alias": null, "name": "actor", @@ -1300,7 +1309,7 @@ v46 = { "args": null, "concreteType": null, "plural": false, - "selections": (v38/*: any*/) + "selections": (v39/*: any*/) }; return { "kind": "Request", @@ -1494,8 +1503,9 @@ return { (v14/*: any*/), (v17/*: any*/), (v18/*: any*/), - (v20/*: any*/), + (v19/*: any*/), (v21/*: any*/), + (v22/*: any*/), (v3/*: any*/) ] } @@ -1517,7 +1527,7 @@ return { "alias": null, "name": "reviewThreads", "storageKey": null, - "args": (v22/*: any*/), + "args": (v23/*: any*/), "concreteType": "PullRequestReviewThreadConnection", "plural": false, "selections": [ @@ -1557,7 +1567,7 @@ return { "args": null, "concreteType": "User", "plural": false, - "selections": (v23/*: any*/) + "selections": (v24/*: any*/) }, { "kind": "ScalarField", @@ -1578,7 +1588,7 @@ return { "alias": null, "name": "comments", "storageKey": null, - "args": (v24/*: any*/), + "args": (v25/*: any*/), "concreteType": "PullRequestReviewCommentConnection", "plural": false, "selections": [ @@ -1602,7 +1612,7 @@ return { "concreteType": "PullRequestReviewComment", "plural": false, "selections": [ - (v25/*: any*/), + (v26/*: any*/), (v4/*: any*/), (v11/*: any*/), (v14/*: any*/), @@ -1614,7 +1624,8 @@ return { "storageKey": null }, (v12/*: any*/), - (v21/*: any*/), + (v22/*: any*/), + (v18/*: any*/), { "kind": "LinkedField", "alias": null, @@ -1631,12 +1642,12 @@ return { (v4/*: any*/) ] }, - (v26/*: any*/), (v27/*: any*/), + (v28/*: any*/), (v13/*: any*/), (v5/*: any*/), - (v18/*: any*/), - (v20/*: any*/), + (v19/*: any*/), + (v21/*: any*/), (v3/*: any*/) ] } @@ -1648,7 +1659,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "comments", - "args": (v24/*: any*/), + "args": (v25/*: any*/), "handle": "connection", "key": "ReviewCommentsAccumulator_comments", "filters": null @@ -1664,7 +1675,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "reviewThreads", - "args": (v22/*: any*/), + "args": (v23/*: any*/), "handle": "connection", "key": "ReviewThreadsAccumulator_reviewThreads", "filters": null @@ -1674,8 +1685,8 @@ return { ] }, (v4/*: any*/), - (v28/*: any*/), - (v30/*: any*/), + (v29/*: any*/), + (v31/*: any*/), { "kind": "LinkedField", "alias": "issue", @@ -1692,9 +1703,9 @@ return { "type": "Issue", "selections": [ (v12/*: any*/), - (v31/*: any*/), - (v5/*: any*/), (v32/*: any*/), + (v5/*: any*/), + (v33/*: any*/), (v11/*: any*/), (v17/*: any*/), { @@ -1702,11 +1713,11 @@ return { "alias": null, "name": "timeline", "storageKey": null, - "args": (v33/*: any*/), + "args": (v34/*: any*/), "concreteType": "IssueTimelineConnection", "plural": false, "selections": [ - (v34/*: any*/), + (v35/*: any*/), { "kind": "LinkedField", "alias": null, @@ -1728,9 +1739,9 @@ return { "selections": [ (v3/*: any*/), (v4/*: any*/), - (v37/*: any*/), - (v39/*: any*/), - (v42/*: any*/) + (v38/*: any*/), + (v40/*: any*/), + (v43/*: any*/) ] } ] @@ -1741,13 +1752,13 @@ return { "kind": "LinkedHandle", "alias": null, "name": "timeline", - "args": (v33/*: any*/), + "args": (v34/*: any*/), "handle": "connection", "key": "IssueTimelineController_timeline", "filters": null }, - (v20/*: any*/), - (v21/*: any*/) + (v21/*: any*/), + (v22/*: any*/) ] } ] @@ -1768,7 +1779,7 @@ return { "type": "PullRequest", "selections": [ (v11/*: any*/), - (v31/*: any*/), + (v32/*: any*/), { "kind": "ScalarField", "alias": null, @@ -1785,7 +1796,7 @@ return { "concreteType": "Repository", "plural": false, "selections": [ - (v28/*: any*/), + (v29/*: any*/), (v5/*: any*/), { "kind": "ScalarField", @@ -1794,12 +1805,12 @@ return { "args": null, "storageKey": null }, - (v30/*: any*/), + (v31/*: any*/), (v4/*: any*/) ] }, (v5/*: any*/), - (v35/*: any*/), + (v36/*: any*/), { "kind": "ScalarField", "alias": null, @@ -1808,7 +1819,7 @@ return { "storageKey": null }, (v12/*: any*/), - (v32/*: any*/), + (v33/*: any*/), { "kind": "ScalarField", "alias": null, @@ -1824,7 +1835,7 @@ return { "args": null, "concreteType": "PullRequestCommitConnection", "plural": false, - "selections": (v19/*: any*/) + "selections": (v20/*: any*/) }, (v17/*: any*/), { @@ -1832,11 +1843,11 @@ return { "alias": null, "name": "commits", "storageKey": null, - "args": (v43/*: any*/), + "args": (v44/*: any*/), "concreteType": "PullRequestCommitConnection", "plural": false, "selections": [ - (v34/*: any*/), + (v35/*: any*/), { "kind": "LinkedField", "alias": null, @@ -1876,7 +1887,7 @@ return { "plural": false, "selections": [ (v16/*: any*/), - (v28/*: any*/), + (v29/*: any*/), { "kind": "ScalarField", "alias": null, @@ -1907,7 +1918,7 @@ return { "args": null, "storageKey": null }, - (v41/*: any*/), + (v42/*: any*/), (v5/*: any*/) ] }, @@ -1923,7 +1934,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "commits", - "args": (v43/*: any*/), + "args": (v44/*: any*/), "handle": "connection", "key": "prCommitsView_commits", "filters": null @@ -2036,7 +2047,7 @@ return { "args": null, "concreteType": null, "plural": false, - "selections": (v29/*: any*/) + "selections": (v30/*: any*/) }, { "kind": "LinkedField", @@ -2047,7 +2058,7 @@ return { "concreteType": "Repository", "plural": false, "selections": [ - (v30/*: any*/), + (v31/*: any*/), (v4/*: any*/) ] }, @@ -2056,11 +2067,11 @@ return { "alias": null, "name": "timeline", "storageKey": null, - "args": (v33/*: any*/), + "args": (v34/*: any*/), "concreteType": "PullRequestTimelineConnection", "plural": false, "selections": [ - (v34/*: any*/), + (v35/*: any*/), { "kind": "LinkedField", "alias": null, @@ -2082,12 +2093,12 @@ return { "selections": [ (v3/*: any*/), (v4/*: any*/), - (v37/*: any*/), + (v38/*: any*/), { "kind": "InlineFragment", "type": "CommitCommentThread", "selections": [ - (v45/*: any*/), + (v46/*: any*/), { "kind": "LinkedField", "alias": null, @@ -2131,13 +2142,13 @@ return { "args": null, "concreteType": null, "plural": false, - "selections": (v36/*: any*/) + "selections": (v37/*: any*/) }, - (v45/*: any*/), + (v46/*: any*/), (v11/*: any*/), - (v27/*: any*/), - (v25/*: any*/), - (v26/*: any*/) + (v28/*: any*/), + (v26/*: any*/), + (v27/*: any*/) ] } ] @@ -2150,7 +2161,7 @@ return { "kind": "InlineFragment", "type": "HeadRefForcePushedEvent", "selections": [ - (v46/*: any*/), + (v47/*: any*/), { "kind": "LinkedField", "alias": null, @@ -2159,7 +2170,7 @@ return { "args": null, "concreteType": "Commit", "plural": false, - "selections": (v44/*: any*/) + "selections": (v45/*: any*/) }, { "kind": "LinkedField", @@ -2169,17 +2180,17 @@ return { "args": null, "concreteType": "Commit", "plural": false, - "selections": (v44/*: any*/) + "selections": (v45/*: any*/) }, - (v27/*: any*/) + (v28/*: any*/) ] }, { "kind": "InlineFragment", "type": "MergedEvent", "selections": [ + (v47/*: any*/), (v46/*: any*/), - (v45/*: any*/), { "kind": "ScalarField", "alias": null, @@ -2187,11 +2198,11 @@ return { "args": null, "storageKey": null }, - (v27/*: any*/) + (v28/*: any*/) ] }, - (v39/*: any*/), - (v42/*: any*/) + (v40/*: any*/), + (v43/*: any*/) ] } ] @@ -2202,13 +2213,13 @@ return { "kind": "LinkedHandle", "alias": null, "name": "timeline", - "args": (v33/*: any*/), + "args": (v34/*: any*/), "handle": "connection", "key": "prTimelineContainer_timeline", "filters": null }, - (v20/*: any*/), - (v21/*: any*/) + (v21/*: any*/), + (v22/*: any*/) ] } ] @@ -2221,7 +2232,7 @@ return { "operationKind": "query", "name": "issueishDetailContainerQuery", "id": null, - "text": "query issueishDetailContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $issueishNumber: Int!\n $timelineCount: Int!\n $timelineCursor: String\n $commitCount: Int!\n $commitCursor: String\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n issueish: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n }\n ... on Node {\n id\n }\n }\n ...issueishDetailController_repository_1mXVvq\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment issueishDetailController_repository_1mXVvq on Repository {\n ...issueDetailView_repository\n ...prCheckoutController_repository\n ...prDetailView_repository\n name\n owner {\n __typename\n login\n id\n }\n issue: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on Issue {\n title\n number\n ...issueDetailView_issue_3D8CP9\n }\n ... on Node {\n id\n }\n }\n pullRequest: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n title\n number\n ...prCheckoutController_pullRequest\n ...prDetailView_pullRequest_1TnD8A\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment issueDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment issueDetailView_issue_3D8CP9 on Issue {\n id\n __typename\n url\n state\n number\n title\n bodyHTML\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...issueTimelineController_issue_3D8CP9\n ...emojiReactionsView_reactable\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment prDetailView_pullRequest_1TnD8A on PullRequest {\n id\n __typename\n url\n isCrossRepository\n changedFiles\n state\n number\n title\n bodyHTML\n baseRefName\n headRefName\n countedCommits: commits {\n totalCount\n }\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...prCommitsView_pullRequest_38TpXw\n ...prStatusesView_pullRequest\n ...prTimelineController_pullRequest_3D8CP9\n ...emojiReactionsController_reactable\n}\n\nfragment prCommitsView_pullRequest_38TpXw on PullRequest {\n url\n commits(first: $commitCount, after: $commitCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n commit {\n id\n ...prCommitView_item\n }\n id\n __typename\n }\n }\n }\n}\n\nfragment prStatusesView_pullRequest on PullRequest {\n id\n recentCommits: commits(last: 1) {\n edges {\n node {\n commit {\n status {\n state\n contexts {\n id\n state\n ...prStatusContextView_context\n }\n id\n }\n id\n }\n id\n }\n }\n }\n}\n\nfragment prTimelineController_pullRequest_3D8CP9 on PullRequest {\n url\n ...headRefForcePushedEventView_issueish\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...mergedEventView_item\n ...headRefForcePushedEventView_item\n ...commitCommentThreadView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment headRefForcePushedEventView_issueish on PullRequest {\n headRefName\n headRepositoryOwner {\n __typename\n login\n id\n }\n repository {\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment commitsView_nodes on Commit {\n id\n author {\n name\n user {\n login\n id\n }\n }\n ...commitView_commit\n}\n\nfragment issueCommentView_item on IssueComment {\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n bodyHTML\n createdAt\n url\n}\n\nfragment mergedEventView_item on MergedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n mergeRefName\n createdAt\n}\n\nfragment headRefForcePushedEventView_item on HeadRefForcePushedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n beforeCommit {\n oid\n id\n }\n afterCommit {\n oid\n id\n }\n createdAt\n}\n\nfragment commitCommentThreadView_item on CommitCommentThread {\n commit {\n oid\n id\n }\n comments(first: 100) {\n edges {\n node {\n id\n ...commitCommentView_item\n }\n }\n }\n}\n\nfragment crossReferencedEventsView_nodes on CrossReferencedEvent {\n id\n referencedAt\n isCrossRepository\n actor {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n source {\n __typename\n ... on RepositoryNode {\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n ...crossReferencedEventView_item\n}\n\nfragment crossReferencedEventView_item on CrossReferencedEvent {\n id\n isCrossRepository\n source {\n __typename\n ... on Issue {\n number\n title\n url\n issueState: state\n }\n ... on PullRequest {\n number\n title\n url\n prState: state\n }\n ... on RepositoryNode {\n repository {\n name\n isPrivate\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment commitCommentView_item on CommitComment {\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n bodyHTML\n createdAt\n path\n position\n}\n\nfragment commitView_commit on Commit {\n author {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n committer {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n authoredByCommitter\n sha: oid\n message\n messageHeadlineHTML\n commitUrl\n}\n\nfragment prStatusContextView_context on StatusContext {\n context\n description\n state\n targetUrl\n}\n\nfragment prCommitView_item on Commit {\n committer {\n avatarUrl\n name\n date\n }\n messageHeadline\n messageBody\n shortSha: abbreviatedOid\n sha: oid\n url\n}\n\nfragment issueTimelineController_issue_3D8CP9 on Issue {\n url\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n", + "text": "query issueishDetailContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $issueishNumber: Int!\n $timelineCount: Int!\n $timelineCursor: String\n $commitCount: Int!\n $commitCursor: String\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n issueish: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n }\n ... on Node {\n id\n }\n }\n ...issueishDetailController_repository_1mXVvq\n id\n }\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment issueishDetailController_repository_1mXVvq on Repository {\n ...issueDetailView_repository\n ...prCheckoutController_repository\n ...prDetailView_repository\n name\n owner {\n __typename\n login\n id\n }\n issue: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on Issue {\n title\n number\n ...issueDetailView_issue_3D8CP9\n }\n ... on Node {\n id\n }\n }\n pullRequest: issueOrPullRequest(number: $issueishNumber) {\n __typename\n ... on PullRequest {\n title\n number\n ...prCheckoutController_pullRequest\n ...prDetailView_pullRequest_1TnD8A\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment issueDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment prDetailView_repository on Repository {\n id\n name\n owner {\n __typename\n login\n id\n }\n}\n\nfragment issueDetailView_issue_3D8CP9 on Issue {\n id\n __typename\n url\n state\n number\n title\n bodyHTML\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...issueTimelineController_issue_3D8CP9\n ...emojiReactionsView_reactable\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment prDetailView_pullRequest_1TnD8A on PullRequest {\n id\n __typename\n url\n isCrossRepository\n changedFiles\n state\n number\n title\n bodyHTML\n baseRefName\n headRefName\n countedCommits: commits {\n totalCount\n }\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n ...prCommitsView_pullRequest_38TpXw\n ...prStatusesView_pullRequest\n ...prTimelineController_pullRequest_3D8CP9\n ...emojiReactionsController_reactable\n}\n\nfragment prCommitsView_pullRequest_38TpXw on PullRequest {\n url\n commits(first: $commitCount, after: $commitCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n commit {\n id\n ...prCommitView_item\n }\n id\n __typename\n }\n }\n }\n}\n\nfragment prStatusesView_pullRequest on PullRequest {\n id\n recentCommits: commits(last: 1) {\n edges {\n node {\n commit {\n status {\n state\n contexts {\n id\n state\n ...prStatusContextView_context\n }\n id\n }\n id\n }\n id\n }\n }\n }\n}\n\nfragment prTimelineController_pullRequest_3D8CP9 on PullRequest {\n url\n ...headRefForcePushedEventView_issueish\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...mergedEventView_item\n ...headRefForcePushedEventView_item\n ...commitCommentThreadView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment headRefForcePushedEventView_issueish on PullRequest {\n headRefName\n headRepositoryOwner {\n __typename\n login\n id\n }\n repository {\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment commitsView_nodes on Commit {\n id\n author {\n name\n user {\n login\n id\n }\n }\n ...commitView_commit\n}\n\nfragment issueCommentView_item on IssueComment {\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n bodyHTML\n createdAt\n url\n}\n\nfragment mergedEventView_item on MergedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n mergeRefName\n createdAt\n}\n\nfragment headRefForcePushedEventView_item on HeadRefForcePushedEvent {\n actor {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n beforeCommit {\n oid\n id\n }\n afterCommit {\n oid\n id\n }\n createdAt\n}\n\nfragment commitCommentThreadView_item on CommitCommentThread {\n commit {\n oid\n id\n }\n comments(first: 100) {\n edges {\n node {\n id\n ...commitCommentView_item\n }\n }\n }\n}\n\nfragment crossReferencedEventsView_nodes on CrossReferencedEvent {\n id\n referencedAt\n isCrossRepository\n actor {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n source {\n __typename\n ... on RepositoryNode {\n repository {\n name\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n ...crossReferencedEventView_item\n}\n\nfragment crossReferencedEventView_item on CrossReferencedEvent {\n id\n isCrossRepository\n source {\n __typename\n ... on Issue {\n number\n title\n url\n issueState: state\n }\n ... on PullRequest {\n number\n title\n url\n prState: state\n }\n ... on RepositoryNode {\n repository {\n name\n isPrivate\n owner {\n __typename\n login\n id\n }\n id\n }\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment commitCommentView_item on CommitComment {\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n commit {\n oid\n id\n }\n bodyHTML\n createdAt\n path\n position\n}\n\nfragment commitView_commit on Commit {\n author {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n committer {\n name\n avatarUrl\n user {\n login\n id\n }\n }\n authoredByCommitter\n sha: oid\n message\n messageHeadlineHTML\n commitUrl\n}\n\nfragment prStatusContextView_context on StatusContext {\n context\n description\n state\n targetUrl\n}\n\nfragment prCommitView_item on Commit {\n committer {\n avatarUrl\n name\n date\n }\n messageHeadline\n messageBody\n shortSha: abbreviatedOid\n sha: oid\n url\n}\n\nfragment issueTimelineController_issue_3D8CP9 on Issue {\n url\n timeline(first: $timelineCount, after: $timelineCursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n __typename\n ...commitsView_nodes\n ...issueCommentView_item\n ...crossReferencedEventsView_nodes\n ... on Node {\n id\n }\n }\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n viewerCanUpdate\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n", "metadata": {} } }; diff --git a/lib/containers/__generated__/reviewsContainerQuery.graphql.js b/lib/containers/__generated__/reviewsContainerQuery.graphql.js index b930903f64..cf0ec3271a 100644 --- a/lib/containers/__generated__/reviewsContainerQuery.graphql.js +++ b/lib/containers/__generated__/reviewsContainerQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 3d469bf630edfedbdb5ab0c6e8ee18d2 + * @relayHash 08df4a78972ce536e88298bb6478d0e8 */ /* eslint-disable */ @@ -134,6 +134,7 @@ fragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest { id } } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable __typename @@ -192,6 +193,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -451,11 +453,18 @@ v17 = { v18 = { "kind": "ScalarField", "alias": null, - "name": "authorAssociation", + "name": "viewerCanUpdate", "args": null, "storageKey": null }, v19 = { + "kind": "ScalarField", + "alias": null, + "name": "authorAssociation", + "args": null, + "storageKey": null +}, +v20 = { "kind": "LinkedField", "alias": null, "name": "reactionGroups", @@ -498,14 +507,14 @@ v19 = { } ] }, -v20 = { +v21 = { "kind": "ScalarField", "alias": null, "name": "viewerCanReact", "args": null, "storageKey": null }, -v21 = [ +v22 = [ { "kind": "Variable", "name": "after", @@ -519,7 +528,7 @@ v21 = [ "type": "Int" } ], -v22 = [ +v23 = [ { "kind": "Variable", "name": "after", @@ -724,6 +733,7 @@ return { (v18/*: any*/), (v19/*: any*/), (v20/*: any*/), + (v21/*: any*/), (v5/*: any*/) ] } @@ -745,7 +755,7 @@ return { "alias": null, "name": "reviewThreads", "storageKey": null, - "args": (v21/*: any*/), + "args": (v22/*: any*/), "concreteType": "PullRequestReviewThreadConnection", "plural": false, "selections": [ @@ -809,7 +819,7 @@ return { "alias": null, "name": "comments", "storageKey": null, - "args": (v22/*: any*/), + "args": (v23/*: any*/), "concreteType": "PullRequestReviewCommentConnection", "plural": false, "selections": [ @@ -851,7 +861,8 @@ return { "storageKey": null }, (v14/*: any*/), - (v20/*: any*/), + (v21/*: any*/), + (v18/*: any*/), { "kind": "LinkedField", "alias": null, @@ -884,8 +895,8 @@ return { }, (v15/*: any*/), (v9/*: any*/), - (v18/*: any*/), (v19/*: any*/), + (v20/*: any*/), (v5/*: any*/) ] } @@ -897,7 +908,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "comments", - "args": (v22/*: any*/), + "args": (v23/*: any*/), "handle": "connection", "key": "ReviewCommentsAccumulator_comments", "filters": null @@ -913,7 +924,7 @@ return { "kind": "LinkedHandle", "alias": null, "name": "reviewThreads", - "args": (v21/*: any*/), + "args": (v22/*: any*/), "handle": "connection", "key": "ReviewThreadsAccumulator_reviewThreads", "filters": null @@ -979,7 +990,7 @@ return { "operationKind": "query", "name": "reviewsContainerQuery", "id": null, - "text": "query reviewsContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $prNumber: Int!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n ...reviewsController_repository\n pullRequest(number: $prNumber) {\n headRefOid\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n ...reviewsController_pullRequest\n id\n }\n id\n }\n viewer {\n ...reviewsController_viewer\n id\n }\n}\n\nfragment reviewsController_repository on Repository {\n ...prCheckoutController_repository\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewsController_pullRequest on PullRequest {\n id\n ...prCheckoutController_pullRequest\n}\n\nfragment reviewsController_viewer on User {\n id\n login\n avatarUrl\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n", + "text": "query reviewsContainerQuery(\n $repoOwner: String!\n $repoName: String!\n $prNumber: Int!\n $reviewCount: Int!\n $reviewCursor: String\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n $commentCursor: String\n) {\n repository(owner: $repoOwner, name: $repoName) {\n ...reviewsController_repository\n pullRequest(number: $prNumber) {\n headRefOid\n ...aggregatedReviewsContainer_pullRequest_qdneZ\n ...reviewsController_pullRequest\n id\n }\n id\n }\n viewer {\n ...reviewsController_viewer\n id\n }\n}\n\nfragment reviewsController_repository on Repository {\n ...prCheckoutController_repository\n}\n\nfragment aggregatedReviewsContainer_pullRequest_qdneZ on PullRequest {\n id\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n ...reviewThreadsAccumulator_pullRequest_CKDvj\n}\n\nfragment reviewsController_pullRequest on PullRequest {\n id\n ...prCheckoutController_pullRequest\n}\n\nfragment reviewsController_viewer on User {\n id\n login\n avatarUrl\n}\n\nfragment prCheckoutController_pullRequest on PullRequest {\n number\n headRefName\n headRepository {\n name\n url\n sshUrl\n owner {\n __typename\n login\n id\n }\n id\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n viewerCanUpdate\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_CKDvj on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n\nfragment prCheckoutController_repository on Repository {\n name\n owner {\n __typename\n login\n id\n }\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js b/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js index e2a463e3f9..48cd182bbd 100644 --- a/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewCommentsAccumulatorQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash e9b1697b85a36fcbb4a8071b04ab4558 + * @relayHash c99d31c7feadf71f8680cfcf559b8aa4 */ /* eslint-disable */ @@ -67,6 +67,7 @@ fragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -330,6 +331,13 @@ return { "args": null, "storageKey": null }, + { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null + }, { "kind": "LinkedField", "alias": null, @@ -456,7 +464,7 @@ return { "operationKind": "query", "name": "reviewCommentsAccumulatorQuery", "id": null, - "text": "query reviewCommentsAccumulatorQuery(\n $id: ID!\n $commentCount: Int!\n $commentCursor: String\n) {\n node(id: $id) {\n __typename\n ... on PullRequestReviewThread {\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n }\n id\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query reviewCommentsAccumulatorQuery(\n $id: ID!\n $commentCount: Int!\n $commentCursor: String\n) {\n node(id: $id) {\n __typename\n ... on PullRequestReviewThread {\n ...reviewCommentsAccumulator_reviewThread_1VbUmL\n }\n id\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1VbUmL on PullRequestReviewThread {\n id\n comments(first: $commentCount, after: $commentCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js b/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js index 84c0c755e9..d38d6de545 100644 --- a/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewCommentsAccumulator_reviewThread.graphql.js @@ -34,6 +34,7 @@ export type reviewCommentsAccumulator_reviewThread = {| +isMinimized: boolean, +state: PullRequestReviewCommentState, +viewerCanReact: boolean, + +viewerCanUpdate: boolean, +path: string, +position: ?number, +createdAt: any, @@ -198,6 +199,13 @@ return { "args": null, "storageKey": null }, + { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null + }, { "kind": "LinkedField", "alias": null, @@ -275,5 +283,5 @@ return { }; })(); // prettier-ignore -(node/*: any*/).hash = 'd5a80482dbc1e2684264d0e88bfe90b3'; +(node/*: any*/).hash = '2716996f7cb548d6f3a3894f5d51193a'; module.exports = node; diff --git a/lib/containers/accumulators/__generated__/reviewSummariesAccumulatorQuery.graphql.js b/lib/containers/accumulators/__generated__/reviewSummariesAccumulatorQuery.graphql.js index 0d4d87b8c2..ef6cef0038 100644 --- a/lib/containers/accumulators/__generated__/reviewSummariesAccumulatorQuery.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewSummariesAccumulatorQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 4b35b7a28de146dbc762d73e291d02dd + * @relayHash 8744660481fe58cf58f55c9cc75a3b10 */ /* eslint-disable */ @@ -70,6 +70,7 @@ fragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest { id } } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable __typename @@ -351,6 +352,13 @@ return { (v3/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -434,7 +442,7 @@ return { "operationKind": "query", "name": "reviewSummariesAccumulatorQuery", "id": null, - "text": "query reviewSummariesAccumulatorQuery(\n $url: URI!\n $reviewCount: Int!\n $reviewCursor: String\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query reviewSummariesAccumulatorQuery(\n $url: URI!\n $reviewCount: Int!\n $reviewCursor: String\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewSummariesAccumulator_pullRequest_2zzc96\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewSummariesAccumulator_pullRequest_2zzc96 on PullRequest {\n url\n reviews(first: $reviewCount, after: $reviewCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n lastEditedAt\n url\n author {\n __typename\n login\n avatarUrl\n url\n ... on Node {\n id\n }\n }\n viewerCanUpdate\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/__generated__/reviewSummariesAccumulator_pullRequest.graphql.js b/lib/containers/accumulators/__generated__/reviewSummariesAccumulator_pullRequest.graphql.js index 9b4bc78dc0..3f42cee6d8 100644 --- a/lib/containers/accumulators/__generated__/reviewSummariesAccumulator_pullRequest.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewSummariesAccumulator_pullRequest.graphql.js @@ -35,6 +35,7 @@ export type reviewSummariesAccumulator_pullRequest = {| +avatarUrl: any, +url: any, |}, + +viewerCanUpdate: boolean, +authorAssociation: CommentAuthorAssociation, +$fragmentRefs: emojiReactionsController_reactable$ref, |}, @@ -144,38 +145,39 @@ return { "concreteType": "PullRequestReview", "plural": false, "selections": [ + (v0/*: any*/), { "kind": "ScalarField", "alias": null, - "name": "lastEditedAt", + "name": "id", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "id", + "name": "bodyHTML", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "bodyHTML", + "name": "state", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "state", + "name": "submittedAt", "args": null, "storageKey": null }, { "kind": "ScalarField", "alias": null, - "name": "submittedAt", + "name": "lastEditedAt", "args": null, "storageKey": null }, @@ -186,7 +188,6 @@ return { "args": null, "storageKey": null }, - (v0/*: any*/), { "kind": "LinkedField", "alias": null, @@ -213,6 +214,13 @@ return { (v0/*: any*/) ] }, + { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -242,5 +250,5 @@ return { }; })(); // prettier-ignore -(node/*: any*/).hash = '8f35b05f3801e46aff95d3e85f6313f6'; +(node/*: any*/).hash = '4ac732c2325cedd6e8e90bb5c140cc1a'; module.exports = node; diff --git a/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js b/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js index d209d8493b..587d70d35f 100644 --- a/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js +++ b/lib/containers/accumulators/__generated__/reviewThreadsAccumulatorQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash ae118b6a8035c1d13132cdeed250a0b6 + * @relayHash 77537dff567439551ae3355cb2972939 */ /* eslint-disable */ @@ -96,6 +96,7 @@ fragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThrea isMinimized state viewerCanReact + viewerCanUpdate path position createdAt @@ -453,6 +454,13 @@ return { "args": null, "storageKey": null }, + { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null + }, { "kind": "LinkedField", "alias": null, @@ -589,7 +597,7 @@ return { "operationKind": "query", "name": "reviewThreadsAccumulatorQuery", "id": null, - "text": "query reviewThreadsAccumulatorQuery(\n $url: URI!\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewThreadsAccumulator_pullRequest_3dVVow\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_3dVVow on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1UlnwR\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThread {\n id\n comments(first: $commentCount) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "query reviewThreadsAccumulatorQuery(\n $url: URI!\n $threadCount: Int!\n $threadCursor: String\n $commentCount: Int!\n) {\n resource(url: $url) {\n __typename\n ... on PullRequest {\n ...reviewThreadsAccumulator_pullRequest_3dVVow\n }\n ... on Node {\n id\n }\n }\n}\n\nfragment reviewThreadsAccumulator_pullRequest_3dVVow on PullRequest {\n url\n reviewThreads(first: $threadCount, after: $threadCursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n isResolved\n resolvedBy {\n login\n id\n }\n viewerCanResolve\n viewerCanUnresolve\n ...reviewCommentsAccumulator_reviewThread_1UlnwR\n __typename\n }\n }\n }\n}\n\nfragment reviewCommentsAccumulator_reviewThread_1UlnwR on PullRequestReviewThread {\n id\n comments(first: $commentCount) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n cursor\n node {\n id\n author {\n __typename\n avatarUrl\n login\n url\n ... on Node {\n id\n }\n }\n bodyHTML\n body\n isMinimized\n state\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n __typename\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; diff --git a/lib/containers/accumulators/review-comments-accumulator.js b/lib/containers/accumulators/review-comments-accumulator.js index 603d76bb71..57f3089e9b 100644 --- a/lib/containers/accumulators/review-comments-accumulator.js +++ b/lib/containers/accumulators/review-comments-accumulator.js @@ -74,6 +74,7 @@ export default createPaginationContainer(BareReviewCommentsAccumulator, { isMinimized state viewerCanReact + viewerCanUpdate path position createdAt diff --git a/lib/containers/accumulators/review-summaries-accumulator.js b/lib/containers/accumulators/review-summaries-accumulator.js index 947f13ea00..f5f11a965f 100644 --- a/lib/containers/accumulators/review-summaries-accumulator.js +++ b/lib/containers/accumulators/review-summaries-accumulator.js @@ -81,6 +81,7 @@ export default createPaginationContainer(BareReviewSummariesAccumulator, { avatarUrl url } + viewerCanUpdate authorAssociation ...emojiReactionsController_reactable } From ec49a59347715facc52760928ed0beb1fb9eb7b1 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Thu, 9 May 2019 16:30:08 -0400 Subject: [PATCH 65/90] only show edit option if user has the right permission --- lib/views/actionable-review-view.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index a9136a80de..cf3d566395 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -108,24 +108,26 @@ export default class ActionableReviewView extends React.Component { }); } - showActionsMenu = (event, comment, author) => { + showActionsMenu = (event, content, author) => { event.preventDefault(); const menu = new Menu(); - menu.append(new MenuItem({ - label: 'Edit', - click: () => this.setState({editing: true}), - })); + if (content.viewerCanUpdate) { + menu.append(new MenuItem({ + label: 'Edit', + click: () => this.setState({editing: true}), + })); + } menu.append(new MenuItem({ label: 'Open on GitHub', - click: () => this.openOnGitHub(comment.url), + click: () => this.openOnGitHub(content.url), })); menu.append(new MenuItem({ label: 'Report abuse', - click: () => this.reportAbuse(comment.url, author.login), + click: () => this.reportAbuse(content.url, author.login), })); menu.popup(remote.getCurrentWindow()); From 8dc48a6cc2828f4a6ebfc5ae61c0204f6e43b61d Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 09:36:23 -0400 Subject: [PATCH 66/90] PropTypes: confirm is a func :ok_hand: --- lib/containers/reviews-container.js | 2 +- lib/controllers/reviews-controller.js | 2 +- lib/items/reviews-item.js | 2 +- lib/views/reviews-view.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/containers/reviews-container.js b/lib/containers/reviews-container.js index af5663d1e4..904a16dd83 100644 --- a/lib/containers/reviews-container.js +++ b/lib/containers/reviews-container.js @@ -40,7 +40,7 @@ export default class ReviewsContainer extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, - confirm: PropTypes.object.isRequired, + confirm: PropTypes.func.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 6c8f5e5aa6..b5a69ca52a 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -66,7 +66,7 @@ export class BareReviewsController extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, - confirm: PropTypes.object.isRequired, + confirm: PropTypes.func.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/items/reviews-item.js b/lib/items/reviews-item.js index f989e99cbc..7eb7bcca12 100644 --- a/lib/items/reviews-item.js +++ b/lib/items/reviews-item.js @@ -25,7 +25,7 @@ export default class ReviewsItem extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, - confirm: PropTypes.object.isRequired, + confirm: PropTypes.func.isRequired, // Action methods reportMutationErrors: PropTypes.func.isRequired, diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index 19e08ed2ef..12dcbd9a46 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -80,7 +80,7 @@ export default class ReviewsView extends React.Component { config: PropTypes.object.isRequired, commands: PropTypes.object.isRequired, tooltips: PropTypes.object.isRequired, - confirm: PropTypes.object.isRequired, + confirm: PropTypes.func.isRequired, // Action methods openFile: PropTypes.func.isRequired, From fcd563f4927fc0cbdb5d1289ca31001764bf186e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 09:37:43 -0400 Subject: [PATCH 67/90] Focus the TextEditor when entering an edit state --- lib/views/actionable-review-view.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index cf3d566395..7285abd99b 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -23,6 +23,12 @@ export default class ActionableReviewView extends React.Component { this.state = {editing: false}; } + componentDidUpdate(prevProps, prevState) { + if (this.state.editing && !prevState.editing) { + this.refEditor.map(e => e.getElement().focus()); + } + } + render() { return this.state.editing ? this.renderEditor() : this.props.render(this.showActionsMenu); } From d96a0bd32e1e40a7e0fd90e5856867ceb05e5a99 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 09:55:11 -0400 Subject: [PATCH 68/90] Drill the CommandRegistry into ActionableReviewView --- lib/views/actionable-review-view.js | 8 ++++++++ lib/views/review-comment-view.js | 11 ++++++++++- lib/views/reviews-view.js | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 7285abd99b..35a193c787 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -10,10 +10,18 @@ const {Menu, MenuItem} = remote; export default class ActionableReviewView extends React.Component { static propTypes = { + // Model originalContent: PropTypes.object.isRequired, isPosting: PropTypes.bool, + + // Atom environment + commands: PropTypes.object.isRequired, confirm: PropTypes.func.isRequired, + + // Action methods contentUpdater: PropTypes.func.isRequired, + + // Render prop render: PropTypes.func.isRequired, } diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index b830b42a1c..d126ac6991 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -12,16 +12,24 @@ import ActionableReviewView from './actionable-review-view'; export default class ReviewCommentView extends React.Component { static propTypes = { + // Model comment: PropTypes.object.isRequired, isPosting: PropTypes.bool.isRequired, + + // Atom environment confirm: PropTypes.func.isRequired, tooltips: PropTypes.object.isRequired, + commands: PropTypes.object.isRequired, + + // Render props renderEditedLink: PropTypes.func.isRequired, renderAuthorAssociation: PropTypes.func.isRequired, - reportMutationErrors: PropTypes.func.isRequired, + + // Action methods openIssueish: PropTypes.func.isRequired, openIssueishLinkInNewTab: PropTypes.func.isRequired, updateComment: PropTypes.func.isRequired, + reportMutationErrors: PropTypes.func.isRequired, } constructor(props) { @@ -35,6 +43,7 @@ export default class ReviewCommentView extends React.Component { originalContent={this.props.comment} isPosting={this.props.isPosting} confirm={this.props.confirm} + commands={this.props.commands} contentUpdater={this.props.updateComment} render={this.renderComment} />); diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index 12dcbd9a46..56688f48a1 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -273,6 +273,7 @@ export default class ReviewsView extends React.Component { { return ( @@ -493,6 +494,7 @@ export default class ReviewsView extends React.Component { renderAuthorAssociation={this.renderAuthorAssociation} isPosting={isPosting} confirm={this.props.confirm} + commands={this.props.commands} updateComment={this.props.updateComment} /> ); From 313ebc8b9f5a9bbd7588f84fa6154d0e9b6b2905 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 09:57:51 -0400 Subject: [PATCH 69/90] Store the TextBuffer as an instance var instead of creating on render --- lib/views/actionable-review-view.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 35a193c787..1a3dc70c94 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -28,11 +28,13 @@ export default class ActionableReviewView extends React.Component { constructor(props) { super(props); this.refEditor = new RefHolder(); + this.buffer = new TextBuffer(); this.state = {editing: false}; } componentDidUpdate(prevProps, prevState) { if (this.state.editing && !prevState.editing) { + this.buffer.setText(this.props.originalContent.body); this.refEditor.map(e => e.getElement().focus()); } } @@ -42,13 +44,11 @@ export default class ActionableReviewView extends React.Component { } renderEditor() { - const buffer = new TextBuffer(); - buffer.setText(this.props.originalContent.body); return (
this.onCancel(buffer.getText() || '')}> + onClick={this.onCancel}> Cancel @@ -75,8 +75,9 @@ export default class ActionableReviewView extends React.Component { ); } - onCancel = text => { - if (text === this.props.originalContent.body) { + + onCancel = () => { + if (this.buffer.getText() === this.props.originalContent.body) { this.setState({editing: false}); } else { const choice = this.props.confirm({ @@ -89,13 +90,13 @@ export default class ActionableReviewView extends React.Component { } } - onSubmitUpdate = text => { - if (text === this.props.originalContent.body || text === '') { + onSubmitUpdate = () => { + if (this.buffer.getText() === this.props.originalContent.body || this.buffer.getText() === '') { this.setState({editing: false}); return; } const didUpdateComment = () => this.setState({editing: false}); - this.props.contentUpdater(this.props.originalContent.id, text, didUpdateComment); + this.props.contentUpdater(this.props.originalContent.id, this.buffer.getText(), didUpdateComment); } reportAbuse = (commentUrl, author) => { From aabd67fe786708a10a3aecc04454e339ea02b88c Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 09:58:43 -0400 Subject: [PATCH 70/90] Bind core:confirm and core:cancel within ActionableReviewView --- lib/views/actionable-review-view.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 1a3dc70c94..60e216ffbc 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -6,6 +6,7 @@ import {TextBuffer} from 'atom'; import AtomTextEditor from '../atom/atom-text-editor'; import RefHolder from '../models/ref-holder'; import {addEvent} from '../reporter-proxy'; +import Commands, {Command} from '../atom/commands'; const {Menu, MenuItem} = remote; export default class ActionableReviewView extends React.Component { @@ -28,6 +29,7 @@ export default class ActionableReviewView extends React.Component { constructor(props) { super(props); this.refEditor = new RefHolder(); + this.refRoot = new RefHolder(); this.buffer = new TextBuffer(); this.state = {editing: false}; } @@ -44,9 +46,10 @@ export default class ActionableReviewView extends React.Component { } renderEditor() { + const className = cx('github-Review-editable', {'github-Review-editable--disabled': this.props.isPosting}); return ( -
+
+ + + + ); + } onCancel = () => { if (this.buffer.getText() === this.props.originalContent.body) { From 410ca78e05c53b1316fc2da24b3b7abe2c581a76 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 10:11:37 -0400 Subject: [PATCH 71/90] We want github:submit-comment for cmd/ctrl-enter --- lib/views/actionable-review-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 60e216ffbc..7aa02ad5d6 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -81,7 +81,7 @@ export default class ActionableReviewView extends React.Component { renderCommands() { return ( - + ); From da6e76df2faedebe678a7dd7b70b9e32ef8730af Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 10:11:48 -0400 Subject: [PATCH 72/90] It helps if you actually call the methods you write --- lib/views/actionable-review-view.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 7aa02ad5d6..772e5377d5 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -50,6 +50,7 @@ export default class ActionableReviewView extends React.Component { return (
+ {this.renderCommands()} Date: Fri, 10 May 2019 10:13:23 -0400 Subject: [PATCH 73/90] Broaden the keymap selector used to bind github:submit-comment This will let cmd/ctrl-enter fire the github:submit-comment event for review summary editors and existing comment editors, too. --- keymaps/git.cson | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keymaps/git.cson b/keymaps/git.cson index 661df96f14..2cfc2172a4 100644 --- a/keymaps/git.cson +++ b/keymaps/git.cson @@ -144,9 +144,9 @@ 'ctrl-=': 'github:more-context' 'ctrl--': 'github:less-context' -'.platform-darwin .github-Review-reply atom-text-editor': +'.platform-darwin .github-Reviews atom-text-editor': 'cmd-enter': 'github:submit-comment' -'.platform-win32 .github-Review-reply atom-text-editor': +'.platform-win32 .github-Reviews atom-text-editor': 'ctrl-enter': 'github:submit-comment' -'.platform-linux .github-Review-reply atom-text-editor': +'.platform-linux .github-Reviews atom-text-editor': 'ctrl-enter': 'github:submit-comment' From fcf00be0fa235b2bf1442e6841de94c5779fca90 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 10:20:58 -0400 Subject: [PATCH 74/90] Include lastEditedAt in mutation responses Without this, the "edited" flair doesn't appear on a review comment or summary you edit until you perform a full refetch. --- .../updatePrReviewCommentMutation.graphql.js | 15 ++++++++++++--- .../updatePrReviewSummaryMutation.graphql.js | 15 ++++++++++++--- lib/mutations/update-pr-review-comment.js | 3 +++ lib/mutations/update-pr-review-summary.js | 3 +++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js index 94a7defb42..31f2d725af 100644 --- a/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js +++ b/lib/mutations/__generated__/updatePrReviewCommentMutation.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash b74d1504cf5b0d4b81427069c26301e3 + * @relayHash aab1d07dc9efcbeed502454b63049d1e */ /* eslint-disable */ @@ -21,6 +21,7 @@ export type updatePrReviewCommentMutationResponse = {| +updatePullRequestReviewComment: ?{| +pullRequestReviewComment: ?{| +id: string, + +lastEditedAt: ?any, +body: string, +bodyHTML: any, |} @@ -40,6 +41,7 @@ mutation updatePrReviewCommentMutation( updatePullRequestReviewComment(input: $input) { pullRequestReviewComment { id + lastEditedAt body bodyHTML } @@ -89,6 +91,13 @@ v1 = [ "args": null, "storageKey": null }, + { + "kind": "ScalarField", + "alias": null, + "name": "lastEditedAt", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -128,11 +137,11 @@ return { "operationKind": "mutation", "name": "updatePrReviewCommentMutation", "id": null, - "text": "mutation updatePrReviewCommentMutation(\n $input: UpdatePullRequestReviewCommentInput!\n) {\n updatePullRequestReviewComment(input: $input) {\n pullRequestReviewComment {\n id\n body\n bodyHTML\n }\n }\n}\n", + "text": "mutation updatePrReviewCommentMutation(\n $input: UpdatePullRequestReviewCommentInput!\n) {\n updatePullRequestReviewComment(input: $input) {\n pullRequestReviewComment {\n id\n lastEditedAt\n body\n bodyHTML\n }\n }\n}\n", "metadata": {} } }; })(); // prettier-ignore -(node/*: any*/).hash = '78e7d083f1783b40873971e9a73c8b0c'; +(node/*: any*/).hash = 'd7b4e823f4604a2b193a1faceb3fcfca'; module.exports = node; diff --git a/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js b/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js index af7996cd76..3c2067bcc8 100644 --- a/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js +++ b/lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 6f60db0700812e37c5c5f835b64af67f + * @relayHash ae10f7769abb8c6656ba8db88412a554 */ /* eslint-disable */ @@ -21,6 +21,7 @@ export type updatePrReviewSummaryMutationResponse = {| +updatePullRequestReview: ?{| +pullRequestReview: ?{| +id: string, + +lastEditedAt: ?any, +body: string, +bodyHTML: any, |} @@ -40,6 +41,7 @@ mutation updatePrReviewSummaryMutation( updatePullRequestReview(input: $input) { pullRequestReview { id + lastEditedAt body bodyHTML } @@ -89,6 +91,13 @@ v1 = [ "args": null, "storageKey": null }, + { + "kind": "ScalarField", + "alias": null, + "name": "lastEditedAt", + "args": null, + "storageKey": null + }, { "kind": "ScalarField", "alias": null, @@ -128,11 +137,11 @@ return { "operationKind": "mutation", "name": "updatePrReviewSummaryMutation", "id": null, - "text": "mutation updatePrReviewSummaryMutation(\n $input: UpdatePullRequestReviewInput!\n) {\n updatePullRequestReview(input: $input) {\n pullRequestReview {\n id\n body\n bodyHTML\n }\n }\n}\n", + "text": "mutation updatePrReviewSummaryMutation(\n $input: UpdatePullRequestReviewInput!\n) {\n updatePullRequestReview(input: $input) {\n pullRequestReview {\n id\n lastEditedAt\n body\n bodyHTML\n }\n }\n}\n", "metadata": {} } }; })(); // prettier-ignore -(node/*: any*/).hash = 'e8da32c47a4d30e206902f1fe4aa4607'; +(node/*: any*/).hash = 'ce6fa7b9b5a5709f8cc8001aa7ba8a15'; module.exports = node; diff --git a/lib/mutations/update-pr-review-comment.js b/lib/mutations/update-pr-review-comment.js index 407bb47fda..2905a02363 100644 --- a/lib/mutations/update-pr-review-comment.js +++ b/lib/mutations/update-pr-review-comment.js @@ -2,12 +2,14 @@ import {commitMutation, graphql} from 'react-relay'; import marked from 'marked'; +import moment from 'moment'; const mutation = graphql` mutation updatePrReviewCommentMutation($input: UpdatePullRequestReviewCommentInput!) { updatePullRequestReviewComment(input: $input) { pullRequestReviewComment { id + lastEditedAt body bodyHTML } @@ -27,6 +29,7 @@ export default (environment, {commentId, commentBody}) => { updatePullRequestReviewComment: { pullRequestReviewComment: { id: commentId, + lastEditedAt: moment().toISOString(), body: commentBody, bodyHTML: marked(commentBody, {gfm: true}), }, diff --git a/lib/mutations/update-pr-review-summary.js b/lib/mutations/update-pr-review-summary.js index 990cc980b1..97ba396a15 100644 --- a/lib/mutations/update-pr-review-summary.js +++ b/lib/mutations/update-pr-review-summary.js @@ -2,12 +2,14 @@ import {commitMutation, graphql} from 'react-relay'; import marked from 'marked'; +import moment from 'moment'; const mutation = graphql` mutation updatePrReviewSummaryMutation($input: UpdatePullRequestReviewInput!) { updatePullRequestReview(input: $input) { pullRequestReview { id + lastEditedAt body bodyHTML } @@ -27,6 +29,7 @@ export default (environment, {reviewId, reviewBody}) => { updatePullRequestReview: { pullRequestReview: { id: reviewId, + lastEditedAt: moment().toISOString(), body: reviewBody, bodyHTML: marked(reviewBody, {gfm: true}), }, From d0ead43bcdd2c792179ad3b31ba50b6e9451bb04 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 10:29:39 -0400 Subject: [PATCH 75/90] Populate missing GraphQL builder fields We added a few fields to PullRequestReview and PullRequestReviewComment, so we need to specify some defaults. --- test/builder/graphql/pr.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/builder/graphql/pr.js b/test/builder/graphql/pr.js index fc272e1996..5752169ab8 100644 --- a/test/builder/graphql/pr.js +++ b/test/builder/graphql/pr.js @@ -34,6 +34,7 @@ export const CommentBuilder = createSpecBuilderClass('PullRequestReviewComment', url: {default: 'https://github.com/atom/github/pull/1829/files#r242224689'}, createdAt: {default: '2018-12-27T17:51:17Z'}, lastEditedAt: {default: null, nullable: true}, + body: {default: 'Lorem ipsum dolor sit amet, te urbanitas appellantur est.'}, bodyHTML: {default: 'Lorem ipsum dolor sit amet, te urbanitas appellantur est.'}, replyTo: {default: null, nullable: true}, isMinimized: {default: false}, @@ -41,6 +42,7 @@ export const CommentBuilder = createSpecBuilderClass('PullRequestReviewComment', state: {default: 'SUBMITTED'}, viewerCanReact: {default: true}, viewerCanMinimize: {default: true}, + viewerCanUpdate: {default: true}, authorAssociation: {default: 'NONE'}, }, 'Node & Comment & Deletable & Updatable & UpdatableComment & Reactable & RepositoryNode'); @@ -62,11 +64,13 @@ export const ReviewBuilder = createSpecBuilderClass('PullRequestReview', { submittedAt: {default: '2018-12-28T20:40:55Z'}, lastEditedAt: {default: null, nullable: true}, url: {default: 'https://github.com/atom/github/pull/1995#pullrequestreview-223120384'}, + body: {default: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit'}, bodyHTML: {default: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit'}, state: {default: 'COMMENTED'}, author: {linked: UserBuilder, default: null, nullable: true}, comments: {linked: CommentConnectionBuilder}, viewerCanReact: {default: true}, + viewerCanUpdate: {default: true}, reactionGroups: {linked: ReactionGroupBuilder, plural: true, singularName: 'reactionGroup'}, authorAssociation: {default: 'NONE'}, }, 'Node & Comment & Deletable & Updatable & UpdatableComment & Reactable & RepositoryNode'); From 6208572dfd5f01976e558fa09b85b81631e6883e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 10:30:06 -0400 Subject: [PATCH 76/90] Add missing props to Reviews(Controller|Container) tests --- test/containers/reviews-container.test.js | 2 ++ test/controllers/reviews-controller.test.js | 1 + 2 files changed, 3 insertions(+) diff --git a/test/containers/reviews-container.test.js b/test/containers/reviews-container.test.js index 25c74488a5..c48d0f8a17 100644 --- a/test/containers/reviews-container.test.js +++ b/test/containers/reviews-container.test.js @@ -65,6 +65,8 @@ describe('ReviewsContainer', function() { config: atomEnv.config, commands: atomEnv.commands, tooltips: atomEnv.tooltips, + confirm: () => {}, + reportMutationErrors: () => {}, ...override, diff --git a/test/controllers/reviews-controller.test.js b/test/controllers/reviews-controller.test.js index 471e6ec3aa..cc6f9f5e67 100644 --- a/test/controllers/reviews-controller.test.js +++ b/test/controllers/reviews-controller.test.js @@ -79,6 +79,7 @@ describe('ReviewsController', function() { config: atomEnv.config, commands: atomEnv.commands, tooltips: atomEnv.tooltips, + confirm: () => {}, reportMutationErrors: () => {}, ...override, From ae196b7130aac2c0337f7479a3d4b1a96587ba89 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 11:10:47 -0400 Subject: [PATCH 77/90] Define builders for added mutations --- test/builder/graphql/mutations.js | 8 ++++++++ test/builder/graphql/query.js | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/test/builder/graphql/mutations.js b/test/builder/graphql/mutations.js index 3bf3455424..b0332c6f83 100644 --- a/test/builder/graphql/mutations.js +++ b/test/builder/graphql/mutations.js @@ -19,10 +19,18 @@ export const AddPullRequestReviewCommentPayloadBuilder = createSpecBuilderClass( commentEdge: {linked: CommentEdgeBuilder}, }); +export const UpdatePullRequestReviewCommentPayloadBuilder = createSpecBuilderClass('UpdatePullRequestReviewCommentPayload', { + pullRequestReviewComment: {linked: CommentBuilder}, +}); + export const SubmitPullRequestReviewPayloadBuilder = createSpecBuilderClass('SubmitPullRequestReviewPayload', { pullRequestReview: {linked: ReviewBuilder}, }); +export const UpdatePullRequestReviewPayloadBuilder = createSpecBuilderClass('UpdatePullRequestReviewPayload', { + pullRequestReview: {linked: ReviewBuilder}, +}); + export const DeletePullRequestReviewPayloadBuilder = createSpecBuilderClass('DeletePullRequestReviewPayload', { pullRequestReview: {linked: ReviewBuilder, nullable: true}, }); diff --git a/test/builder/graphql/query.js b/test/builder/graphql/query.js index 5474e81fae..a0bab7f299 100644 --- a/test/builder/graphql/query.js +++ b/test/builder/graphql/query.js @@ -8,7 +8,9 @@ import {PullRequestBuilder} from './pr'; import { AddPullRequestReviewPayloadBuilder, AddPullRequestReviewCommentPayloadBuilder, + UpdatePullRequestReviewCommentPayloadBuilder, SubmitPullRequestReviewPayloadBuilder, + UpdatePullRequestReviewPayloadBuilder, DeletePullRequestReviewPayloadBuilder, ResolveReviewThreadPayloadBuilder, UnresolveReviewThreadPayloadBuilder, @@ -46,9 +48,11 @@ const QueryBuilder = createSpecBuilderClass('Query', { // Mutations addPullRequestReview: {linked: AddPullRequestReviewPayloadBuilder}, - addPullRequestReviewComment: {linked: AddPullRequestReviewCommentPayloadBuilder}, submitPullRequestReview: {linked: SubmitPullRequestReviewPayloadBuilder}, + updatePullRequestReview: {linked: UpdatePullRequestReviewPayloadBuilder}, deletePullRequestReview: {linked: DeletePullRequestReviewPayloadBuilder}, + addPullRequestReviewComment: {linked: AddPullRequestReviewCommentPayloadBuilder}, + updatePullRequestReviewComment: {linked: UpdatePullRequestReviewCommentPayloadBuilder}, resolveReviewThread: {linked: ResolveReviewThreadPayloadBuilder}, unresolveReviewThread: {linked: UnresolveReviewThreadPayloadBuilder}, addReaction: {linked: AddReactionPayloadBuilder}, From eef469940661b8f7080309830a76a9d0fc3452ef Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 11:11:41 -0400 Subject: [PATCH 78/90] Unit tests for added ReviewsController action methods --- test/controllers/reviews-controller.test.js | 94 +++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/test/controllers/reviews-controller.test.js b/test/controllers/reviews-controller.test.js index cc6f9f5e67..801dbc6f73 100644 --- a/test/controllers/reviews-controller.test.js +++ b/test/controllers/reviews-controller.test.js @@ -27,6 +27,8 @@ import deletePrReviewMutation from '../../lib/mutations/__generated__/deletePrRe import submitPrReviewMutation from '../../lib/mutations/__generated__/submitPrReviewMutation.graphql'; import resolveThreadMutation from '../../lib/mutations/__generated__/resolveReviewThreadMutation.graphql'; import unresolveThreadMutation from '../../lib/mutations/__generated__/unresolveReviewThreadMutation.graphql'; +import updateReviewCommentMutation from '../../lib/mutations/__generated__/updatePrReviewCommentMutation.graphql'; +import updatePrReviewMutation from '../../lib/mutations/__generated__/updatePrReviewSummaryMutation.graphql'; describe('ReviewsController', function() { let atomEnv, relayEnv, localRepository, noop, clock; @@ -604,6 +606,98 @@ describe('ReviewsController', function() { }); }); + describe('editing review comments', function() { + it('calls the review comment update mutation and increments a metric', async function() { + const reportMutationErrors = sinon.spy(); + sinon.stub(reporterProxy, 'addEvent'); + + expectRelayQuery({ + name: updateReviewCommentMutation.operation.name, + variables: { + input: {pullRequestReviewCommentId: 'comment-0', body: 'new text'}, + }, + }, op => relayResponseBuilder(op).build()).resolve(); + + const wrapper = shallow(buildApp({reportMutationErrors})) + .find(PullRequestCheckoutController) + .renderProp('children')(noop); + + await wrapper.find(ReviewsView).prop('updateComment')('comment-0', 'new text'); + + assert.isFalse(reportMutationErrors.called); + assert.isTrue(reporterProxy.addEvent.calledWith('update-review-comment', {package: 'github'})); + }); + + it('creates a notification and and re-throws the error if the comment cannot be updated', async function() { + const reportMutationErrors = sinon.spy(); + sinon.stub(reporterProxy, 'addEvent'); + + expectRelayQuery({ + name: updateReviewCommentMutation.operation.name, + variables: { + input: {pullRequestReviewCommentId: 'comment-0', body: 'new text'}, + }, + }, op => relayResponseBuilder(op).addError('not right now').build()).resolve(); + + const wrapper = shallow(buildApp({reportMutationErrors})) + .find(PullRequestCheckoutController) + .renderProp('children')(noop); + + await assert.isRejected( + wrapper.find(ReviewsView).prop('updateComment')('comment-0', 'new text'), + ); + + assert.isTrue(reportMutationErrors.calledWith('Unable to update comment')); + assert.isFalse(reporterProxy.addEvent.called); + }); + }); + + describe('editing review summaries', function() { + it('calls the review summary update mutation and increments a metric', async function() { + const reportMutationErrors = sinon.spy(); + sinon.stub(reporterProxy, 'addEvent'); + + expectRelayQuery({ + name: updatePrReviewMutation.operation.name, + variables: { + input: {pullRequestReviewId: 'review-0', body: 'stuff'}, + }, + }, op => relayResponseBuilder(op).build()).resolve(); + + const wrapper = shallow(buildApp({reportMutationErrors})) + .find(PullRequestCheckoutController) + .renderProp('children')(noop); + + await wrapper.find(ReviewsView).prop('updateSummary')('review-0', 'stuff'); + + assert.isFalse(reportMutationErrors.called); + assert.isTrue(reporterProxy.addEvent.calledWith('update-review-summary', {package: 'github'})); + }); + + it('creates a notification and and re-throws the error if the summary cannot be updated', async function() { + const reportMutationErrors = sinon.spy(); + sinon.stub(reporterProxy, 'addEvent'); + + expectRelayQuery({ + name: updatePrReviewMutation.operation.name, + variables: { + input: {pullRequestReviewId: 'review-0', body: 'stuff'}, + }, + }, op => relayResponseBuilder(op).addError('not right now').build()).resolve(); + + const wrapper = shallow(buildApp({reportMutationErrors})) + .find(PullRequestCheckoutController) + .renderProp('children')(noop); + + await assert.isRejected( + wrapper.find(ReviewsView).prop('updateSummary')('review-0', 'stuff'), + ); + + assert.isTrue(reportMutationErrors.calledWith('Unable to update review summary')); + assert.isFalse(reporterProxy.addEvent.called); + }); + }); + describe('action methods', function() { let wrapper, openFilesTab, onTabSelected; From 2c5aaad2baf026fe53c858e942098e3563439237 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 11:13:54 -0400 Subject: [PATCH 79/90] Update ReviewsController action method behavior to match the tests I've removed the callback parameter - using Promise fulfillment will be cleaner - and made the update methods re-throw caught mutation errors. I've also updated the callsite in ActionableReviewView to use await and try/catch to manage editing state. Now if the update mutation fails, users won't lose their edits. --- lib/controllers/reviews-controller.js | 8 ++++---- lib/views/actionable-review-view.js | 14 ++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index b5a69ca52a..3931dafa26 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -348,29 +348,29 @@ export class BareReviewsController extends React.Component { } } - updateComment = async (commentId, commentBody, callback) => { + updateComment = async (commentId, commentBody) => { try { await updatePrReviewCommentMutation(this.props.relay.environment, { commentId, commentBody, }); addEvent('update-review-comment', {package: 'github'}); - callback(); } catch (error) { this.props.reportMutationErrors('Unable to update comment', error); + throw error; } } - updateSummary = async (reviewId, reviewBody, callback) => { + updateSummary = async (reviewId, reviewBody) => { try { await updatePrReviewSummaryMutation(this.props.relay.environment, { reviewId, reviewBody, }); addEvent('update-review-summary', {package: 'github'}); - callback(); } catch (error) { this.props.reportMutationErrors('Unable to update review summary', error); + throw error; } } } diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 772e5377d5..1e61afddf9 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -102,13 +102,19 @@ export default class ActionableReviewView extends React.Component { } } - onSubmitUpdate = () => { - if (this.buffer.getText() === this.props.originalContent.body || this.buffer.getText() === '') { + onSubmitUpdate = async () => { + const text = this.buffer.getText(); + if (text === this.props.originalContent.body || text === '') { this.setState({editing: false}); return; } - const didUpdateComment = () => this.setState({editing: false}); - this.props.contentUpdater(this.props.originalContent.id, this.buffer.getText(), didUpdateComment); + + try { + await this.props.contentUpdater(this.props.originalContent.id, text); + this.setState({editing: false}); + } catch (e) { + this.buffer.setText(text); + } } reportAbuse = (commentUrl, author) => { From 22a08c6f752938f462477a65d9208fb0908999cd Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 11:52:39 -0400 Subject: [PATCH 80/90] Test coverage for that last branch --- test/controllers/reviews-controller.test.js | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/controllers/reviews-controller.test.js b/test/controllers/reviews-controller.test.js index 801dbc6f73..87613ea549 100644 --- a/test/controllers/reviews-controller.test.js +++ b/test/controllers/reviews-controller.test.js @@ -133,6 +133,50 @@ describe('ReviewsController', function() { assert.isNull(opWrapper.find(ReviewsView).prop('scrollToThreadID')); }); + it('does not unset a different scrollToThreadID if two highlight actions collide', function() { + clock = sinon.useFakeTimers(); + const wrapper = shallow(buildApp()); + let opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + + assert.deepEqual(opWrapper.find(ReviewsView).prop('threadIDsOpen'), new Set([])); + wrapper.setProps({initThreadID: 'hang-by-a-thread'}); + opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + + assert.deepEqual( + Array.from(opWrapper.find(ReviewsView).prop('threadIDsOpen')), + ['hang-by-a-thread'], + ); + assert.deepEqual( + Array.from(opWrapper.find(ReviewsView).prop('highlightedThreadIDs')), + ['hang-by-a-thread'], + ); + assert.isTrue(opWrapper.find(ReviewsView).prop('commentSectionOpen')); + assert.strictEqual(opWrapper.find(ReviewsView).prop('scrollToThreadID'), 'hang-by-a-thread'); + + clock.tick(1000); + wrapper.setProps({initThreadID: 'caught-in-a-web'}); + opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + + assert.deepEqual( + Array.from(opWrapper.find(ReviewsView).prop('threadIDsOpen')), + ['hang-by-a-thread', 'caught-in-a-web'], + ); + assert.deepEqual( + Array.from(opWrapper.find(ReviewsView).prop('highlightedThreadIDs')), + ['hang-by-a-thread', 'caught-in-a-web'], + ); + assert.isTrue(opWrapper.find(ReviewsView).prop('commentSectionOpen')); + assert.strictEqual(opWrapper.find(ReviewsView).prop('scrollToThreadID'), 'caught-in-a-web'); + + clock.tick(1000); + opWrapper = wrapper.find(PullRequestCheckoutController).renderProp('children')(noop); + assert.deepEqual( + Array.from(opWrapper.find(ReviewsView).prop('highlightedThreadIDs')), + ['caught-in-a-web'], + ); + assert.strictEqual(opWrapper.find(ReviewsView).prop('scrollToThreadID'), 'caught-in-a-web'); + }); + describe('openIssueish', function() { it('opens an IssueishDetailItem for a different issueish', async function() { const wrapper = shallow(buildApp({ From aebdbe7db89d2c1874f32a150fd5bca8f92788d3 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 15:44:32 -0400 Subject: [PATCH 81/90] Pluggable Menu and MenuItem creation This lets us inject mocks to test menu actions without having to do any crazy Electron shenanigans. --- lib/views/actionable-review-view.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/views/actionable-review-view.js b/lib/views/actionable-review-view.js index 1e61afddf9..aa92696ed1 100644 --- a/lib/views/actionable-review-view.js +++ b/lib/views/actionable-review-view.js @@ -21,11 +21,18 @@ export default class ActionableReviewView extends React.Component { // Action methods contentUpdater: PropTypes.func.isRequired, + createMenu: PropTypes.func, + createMenuItem: PropTypes.func, // Render prop render: PropTypes.func.isRequired, } + static defaultProps = { + createMenu: /* istanbul ignore next */ () => new Menu(), + createMenuItem: /* istanbul ignore next */ (...args) => new MenuItem(...args), + } + constructor(props) { super(props); this.refEditor = new RefHolder(); @@ -144,21 +151,21 @@ export default class ActionableReviewView extends React.Component { showActionsMenu = (event, content, author) => { event.preventDefault(); - const menu = new Menu(); + const menu = this.props.createMenu(); if (content.viewerCanUpdate) { - menu.append(new MenuItem({ + menu.append(this.props.createMenuItem({ label: 'Edit', click: () => this.setState({editing: true}), })); } - menu.append(new MenuItem({ + menu.append(this.props.createMenuItem({ label: 'Open on GitHub', click: () => this.openOnGitHub(content.url), })); - menu.append(new MenuItem({ + menu.append(this.props.createMenuItem({ label: 'Report abuse', click: () => this.reportAbuse(content.url, author.login), })); From a6de7c13b8d569d0b8867b03563420c51a0fbd6a Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Fri, 10 May 2019 15:44:57 -0400 Subject: [PATCH 82/90] The Story So Far I've got everything but the cancel button tests. --- test/views/actionable-review-view.test.js | 280 ++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 test/views/actionable-review-view.test.js diff --git a/test/views/actionable-review-view.test.js b/test/views/actionable-review-view.test.js new file mode 100644 index 0000000000..ee8af8efc3 --- /dev/null +++ b/test/views/actionable-review-view.test.js @@ -0,0 +1,280 @@ +import React from 'react'; +import {shallow} from 'enzyme'; +import {shell} from 'electron'; + +import ActionableReviewView from '../../lib/views/actionable-review-view'; +import * as reporterProxy from '../../lib/reporter-proxy'; + +describe('ActionableReviewView', function() { + let atomEnv, mockEvent, mockMenu; + + beforeEach(function() { + atomEnv = global.buildAtomEnvironment(); + + mockEvent = { + preventDefault: sinon.spy(), + }; + + mockMenu = { + append: sinon.spy(), + popup: sinon.spy(), + }; + + sinon.stub(reporterProxy, 'addEvent'); + }); + + afterEach(function() { + atomEnv.destroy(); + }); + + function buildApp(override = {}) { + const props = { + originalContent: {body: 'original'}, + isPosting: false, + commands: atomEnv.commands, + confirm: () => {}, + contentUpdater: () => {}, + render: () =>
, + createMenu: () => mockMenu, + createMenuItem: opts => opts, + ...override, + }; + + return ; + } + + describe('out of editing mode', function() { + it('calls its render prop with a menu-creation function', function() { + const render = sinon.stub().returns(
); + const wrapper = shallow(buildApp({render})); + + assert.isTrue(wrapper.exists('.done')); + + const [showActionsMenu] = render.lastCall.args; + showActionsMenu(mockEvent, {}, {}); + assert.isTrue(mockEvent.preventDefault.called); + assert.isTrue(mockMenu.popup.called); + }); + + describe('the menu', function() { + function triggerMenu(content, author) { + const items = []; + + const wrapper = shallow(buildApp({ + createMenuItem: itemOpts => items.push(itemOpts), + render: showActionsMenu => showActionsMenu(mockEvent, content, author), + })); + + return {items, wrapper}; + } + + it("opens the content object's URL with 'Open on GitHub'", async function() { + sinon.stub(shell, 'openExternal').callsArg(2); + + const item = triggerMenu({url: 'https://github.com'}, {}).items.find(i => i.label === 'Open on GitHub'); + await item.click(); + + assert.isTrue(shell.openExternal.calledWith('https://github.com', {})); + assert.isTrue(reporterProxy.addEvent.calledWith('open-comment-in-browser')); + }); + + it("rejects the promise when 'Open on GitHub' fails", async function() { + sinon.stub(shell, 'openExternal').callsArgWith(2, new Error("I don't feel like it")); + + const item = triggerMenu({url: 'https://github.com'}, {}).items.find(i => i.label === 'Open on GitHub'); + await assert.isRejected(item.click()); + assert.isFalse(reporterProxy.addEvent.called); + }); + + it('opens a prepopulated abuse-reporting link with "Report abuse"', async function() { + sinon.stub(shell, 'openExternal').callsArg(2); + + const item = triggerMenu({url: 'https://github.com/a/b'}, {login: 'tyrion'}) + .items.find(i => i.label === 'Report abuse'); + await item.click(); + + assert.isTrue(shell.openExternal.calledWith( + 'https://github.com/contact/report-content?report=tyrion&content_url=https%3A%2F%2Fgithub.com%2Fa%2Fb', + {}, + )); + assert.isTrue(reporterProxy.addEvent.calledWith('report-abuse')); + }); + + it("rejects the promise when 'Report abuse' fails", async function() { + sinon.stub(shell, 'openExternal').callsArgWith(2, new Error('nah')); + + const item = triggerMenu({url: 'https://github.com/a/b'}, {login: 'tyrion'}) + .items.find(i => i.label === 'Report abuse'); + await assert.isRejected(item.click()); + assert.isFalse(reporterProxy.addEvent.called); + }); + + it('includes an "edit" item only if the content is editable', function() { + assert.isTrue(triggerMenu({viewerCanUpdate: true}, {}).items.some(item => item.label === 'Edit')); + assert.isFalse(triggerMenu({viewerCanUpdate: false}, {}).items.some(item => item.label === 'Edit')); + }); + + it('enters the editing state if the "edit" item is chosen', function() { + const {items, wrapper} = triggerMenu({viewerCanUpdate: true}, {}); + assert.isFalse(wrapper.exists('.github-Review-editable')); + + items.find(i => i.label === 'Edit').click(); + wrapper.update(); + assert.isTrue(wrapper.exists('.github-Review-editable')); + }); + }); + }); + + describe('in editing mode', function() { + let mockEditor, mockEditorElement; + + beforeEach(function() { + mockEditorElement = {focus: sinon.spy()}; + mockEditor = {getElement: () => mockEditorElement}; + }); + + function shallowEditMode(override = {}) { + let editCallback; + const wrapper = shallow(buildApp({ + ...override, + render: showActionsMenu => { + showActionsMenu(mockEvent, {viewerCanUpdate: true}, {}); + if (override.render) { + return override.render(); + } else { + return
; + } + }, + createMenuItem: opts => { + if (opts.label === 'Edit') { + editCallback = opts.click; + } + }, + })); + + wrapper.instance().refEditor.setter(mockEditor); + + editCallback(); + return wrapper.update(); + } + + it('displays a focused editor prepopulated with the original content body and control buttons', function() { + const wrapper = shallowEditMode({ + originalContent: {body: 'this is what it said before'}, + }); + + const editor = wrapper.find('AtomTextEditor'); + assert.strictEqual(editor.prop('buffer').getText(), 'this is what it said before'); + assert.isFalse(editor.prop('readOnly')); + + assert.isTrue(mockEditorElement.focus.called); + + assert.isFalse(wrapper.find('.github-Review-editableCancelButton').prop('disabled')); + assert.isFalse(wrapper.find('.github-Review-updateCommentButton').prop('disabled')); + }); + + it('does not repopulate the buffer when the edit state has not changed', function() { + const wrapper = shallowEditMode({ + originalContent: {body: 'this is what it said before'}, + }); + + assert.strictEqual( + wrapper.find('AtomTextEditor').prop('buffer').getText(), + 'this is what it said before', + ); + assert.strictEqual(mockEditorElement.focus.callCount, 1); + + wrapper.setProps({originalContent: {body: 'nope'}}); + + assert.strictEqual( + wrapper.find('AtomTextEditor').prop('buffer').getText(), + 'this is what it said before', + ); + assert.strictEqual(mockEditorElement.focus.callCount, 1); + }); + + it('disables the editor and buttons while posting is in progress', function() { + const wrapper = shallowEditMode({isPosting: true}); + + assert.isTrue(wrapper.exists('.github-Review-editable--disabled')); + assert.isTrue(wrapper.find('AtomTextEditor').prop('readOnly')); + assert.isTrue(wrapper.find('.github-Review-editableCancelButton').prop('disabled')); + assert.isTrue(wrapper.find('.github-Review-updateCommentButton').prop('disabled')); + }); + + describe('when the submit button is clicked', function() { + it('does nothing and exits edit mode when the buffer is unchanged', async function() { + const contentUpdater = sinon.stub().resolves(); + + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + contentUpdater, + render: () =>
, + }); + + await wrapper.find('.github-Review-updateCommentButton').prop('onClick')(); + assert.isFalse(contentUpdater.called); + assert.isTrue(wrapper.exists('.non-editable')); + }); + + it('does nothing and exits edit mode when the buffer is empty', async function() { + const contentUpdater = sinon.stub().resolves(); + + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + contentUpdater, + render: () =>
, + }); + + wrapper.find('AtomTextEditor').prop('buffer').setText(''); + await wrapper.find('.github-Review-updateCommentButton').prop('onClick')(); + assert.isFalse(contentUpdater.called); + assert.isTrue(wrapper.exists('.non-editable')); + }); + + it('calls the contentUpdater function and exits edit mode when the buffer has changed', async function() { + const contentUpdater = sinon.stub().resolves(); + + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + contentUpdater, + render: () =>
, + }); + + wrapper.find('AtomTextEditor').prop('buffer').setText('different'); + await wrapper.find('.github-Review-updateCommentButton').prop('onClick')(); + assert.isTrue(contentUpdater.calledWith('id-0', 'different')); + + assert.isTrue(wrapper.exists('.non-editable')); + }); + + it('remains in editing mode and preserves the buffer text when unsuccessful', async function() { + const contentUpdater = sinon.stub().rejects(new Error('oh no')); + + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + contentUpdater, + render: () =>
, + }); + + wrapper.find('AtomTextEditor').prop('buffer').setText('different'); + await wrapper.find('.github-Review-updateCommentButton').prop('onClick')(); + assert.isTrue(contentUpdater.calledWith('id-0', 'different')); + + assert.strictEqual(wrapper.find('AtomTextEditor').prop('buffer').getText(), 'different'); + }); + }); + + describe('when the cancel button is clicked', function() { + it('reverts to non-editing mode when the text is unchanged'); + + it('reverts to non-editing mode when the text is empty'); + + describe('when the text has changed', function() { + it('reverts to non-editing mode when the user confirms'); + + it('remains in editing mode when the user cancels'); + }); + }); + }); +}); From 7ec01ea2bac0fa5cab16b508512bbf2870445fdf Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Mon, 13 May 2019 15:03:08 +0200 Subject: [PATCH 83/90] fill in actionable-review-view tests --- test/views/actionable-review-view.test.js | 51 ++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/test/views/actionable-review-view.test.js b/test/views/actionable-review-view.test.js index ee8af8efc3..90568b0cbb 100644 --- a/test/views/actionable-review-view.test.js +++ b/test/views/actionable-review-view.test.js @@ -5,7 +5,7 @@ import {shell} from 'electron'; import ActionableReviewView from '../../lib/views/actionable-review-view'; import * as reporterProxy from '../../lib/reporter-proxy'; -describe('ActionableReviewView', function() { +describe.only('ActionableReviewView', function() { let atomEnv, mockEvent, mockMenu; beforeEach(function() { @@ -266,14 +266,55 @@ describe('ActionableReviewView', function() { }); describe('when the cancel button is clicked', function() { - it('reverts to non-editing mode when the text is unchanged'); + it('reverts to non-editing mode when the text is unchanged', async function() { + const confirm = sinon.stub().returns(0); - it('reverts to non-editing mode when the text is empty'); + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + confirm, + render: () =>
, + }); + + await wrapper.find('.github-Review-editableCancelButton').prop('onClick')(); + assert.isFalse(confirm.called); + assert.isTrue(wrapper.exists('.original')); + }); describe('when the text has changed', function() { - it('reverts to non-editing mode when the user confirms'); + it('reverts to non-editing mode when the user confirms', async function() { + const confirm = sinon.stub().returns(0); + const contentUpdater = sinon.stub().resolves(); + + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + confirm, + contentUpdater, + render: () =>
, + }); + + wrapper.find('AtomTextEditor').prop('buffer').setText('new text'); + await wrapper.find('.github-Review-editableCancelButton').prop('onClick')(); + assert.isTrue(confirm.called); + assert.isFalse(contentUpdater.called); + assert.isFalse(wrapper.exists('.github-Review-editable')); + assert.isTrue(wrapper.exists('.original')); + }); + + it('remains in editing mode when the user cancels', async function() { + const confirm = sinon.stub().returns(1); - it('remains in editing mode when the user cancels'); + const wrapper = shallowEditMode({ + originalContent: {id: 'id-0', body: 'original'}, + confirm, + render: () =>
, + }); + + wrapper.find('AtomTextEditor').prop('buffer').setText('new text'); + await wrapper.find('.github-Review-editableCancelButton').prop('onClick')(); + assert.isTrue(confirm.called); + assert.isTrue(wrapper.exists('.github-Review-editable')); + assert.isFalse(wrapper.exists('.original')); + }); }); }); }); From 16664b4e620ecd014ac5a8b78c5dbdab3799aaf8 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Mon, 13 May 2019 15:03:25 +0200 Subject: [PATCH 84/90] :fire: `.only` --- test/views/actionable-review-view.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/views/actionable-review-view.test.js b/test/views/actionable-review-view.test.js index 90568b0cbb..0c5474cec0 100644 --- a/test/views/actionable-review-view.test.js +++ b/test/views/actionable-review-view.test.js @@ -5,7 +5,7 @@ import {shell} from 'electron'; import ActionableReviewView from '../../lib/views/actionable-review-view'; import * as reporterProxy from '../../lib/reporter-proxy'; -describe.only('ActionableReviewView', function() { +describe('ActionableReviewView', function() { let atomEnv, mockEvent, mockMenu; beforeEach(function() { From 1b625534b3d33571bfa3e98b333dab8e9bdb9c2d Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 13 May 2019 09:40:44 -0400 Subject: [PATCH 85/90] Use renderMarkdown helper in comment update mutations --- lib/mutations/update-pr-review-comment.js | 5 +++-- lib/mutations/update-pr-review-summary.js | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/mutations/update-pr-review-comment.js b/lib/mutations/update-pr-review-comment.js index 2905a02363..72ab054325 100644 --- a/lib/mutations/update-pr-review-comment.js +++ b/lib/mutations/update-pr-review-comment.js @@ -1,9 +1,10 @@ /* istanbul ignore file */ import {commitMutation, graphql} from 'react-relay'; -import marked from 'marked'; import moment from 'moment'; +import {renderMarkdown} from '../helpers'; + const mutation = graphql` mutation updatePrReviewCommentMutation($input: UpdatePullRequestReviewCommentInput!) { updatePullRequestReviewComment(input: $input) { @@ -31,7 +32,7 @@ export default (environment, {commentId, commentBody}) => { id: commentId, lastEditedAt: moment().toISOString(), body: commentBody, - bodyHTML: marked(commentBody, {gfm: true}), + bodyHTML: renderMarkdown(commentBody), }, }, }; diff --git a/lib/mutations/update-pr-review-summary.js b/lib/mutations/update-pr-review-summary.js index 97ba396a15..b8740201cd 100644 --- a/lib/mutations/update-pr-review-summary.js +++ b/lib/mutations/update-pr-review-summary.js @@ -1,9 +1,10 @@ /* istanbul ignore file */ import {commitMutation, graphql} from 'react-relay'; -import marked from 'marked'; import moment from 'moment'; +import {renderMarkdown} from '../helpers'; + const mutation = graphql` mutation updatePrReviewSummaryMutation($input: UpdatePullRequestReviewInput!) { updatePullRequestReview(input: $input) { @@ -31,7 +32,7 @@ export default (environment, {reviewId, reviewBody}) => { id: reviewId, lastEditedAt: moment().toISOString(), body: reviewBody, - bodyHTML: marked(reviewBody, {gfm: true}), + bodyHTML: renderMarkdown(reviewBody), }, }, }; From df060f02e2791297b77009f94432d964fa2aa37b Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 13 May 2019 09:50:02 -0400 Subject: [PATCH 86/90] Include viewerCan(React|Update) in optimistic and real mutation responses --- .../addPrReviewCommentMutation.graphql.js | 58 +++++++++++------ .../addPrReviewMutation.graphql.js | 62 +++++++++++++------ lib/mutations/add-pr-review-comment.js | 8 ++- lib/mutations/add-pr-review.js | 10 ++- 4 files changed, 100 insertions(+), 38 deletions(-) diff --git a/lib/mutations/__generated__/addPrReviewCommentMutation.graphql.js b/lib/mutations/__generated__/addPrReviewCommentMutation.graphql.js index 004a50d995..4858d90159 100644 --- a/lib/mutations/__generated__/addPrReviewCommentMutation.graphql.js +++ b/lib/mutations/__generated__/addPrReviewCommentMutation.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 5665661d41495c80bd3a332f2b4c92f7 + * @relayHash 7db74054a2685fc13fab5c05bd711dca */ /* eslint-disable */ @@ -32,9 +32,11 @@ export type addPrReviewCommentMutationResponse = {| +avatarUrl: any, +login: string, |}, + +body: string, +bodyHTML: any, +isMinimized: boolean, +viewerCanReact: boolean, + +viewerCanUpdate: boolean, +path: string, +position: ?number, +createdAt: any, @@ -69,9 +71,11 @@ mutation addPrReviewCommentMutation( id } } + body bodyHTML isMinimized viewerCanReact + viewerCanUpdate path position createdAt @@ -122,7 +126,7 @@ v1 = [ v2 = { "kind": "ScalarField", "alias": null, - "name": "position", + "name": "path", "args": null, "storageKey": null }, @@ -136,67 +140,81 @@ v3 = { v4 = { "kind": "ScalarField", "alias": null, - "name": "bodyHTML", + "name": "body", "args": null, "storageKey": null }, v5 = { "kind": "ScalarField", "alias": null, - "name": "isMinimized", + "name": "bodyHTML", "args": null, "storageKey": null }, v6 = { "kind": "ScalarField", "alias": null, - "name": "viewerCanReact", + "name": "isMinimized", "args": null, "storageKey": null }, v7 = { "kind": "ScalarField", "alias": null, - "name": "path", + "name": "viewerCanReact", "args": null, "storageKey": null }, v8 = { "kind": "ScalarField", "alias": null, - "name": "avatarUrl", + "name": "viewerCanUpdate", "args": null, "storageKey": null }, v9 = { "kind": "ScalarField", "alias": null, - "name": "login", + "name": "avatarUrl", "args": null, "storageKey": null }, v10 = { "kind": "ScalarField", "alias": null, - "name": "createdAt", + "name": "login", "args": null, "storageKey": null }, v11 = { "kind": "ScalarField", "alias": null, - "name": "lastEditedAt", + "name": "position", "args": null, "storageKey": null }, v12 = { "kind": "ScalarField", "alias": null, - "name": "url", + "name": "createdAt", "args": null, "storageKey": null }, v13 = { + "kind": "ScalarField", + "alias": null, + "name": "lastEditedAt", + "args": null, + "storageKey": null +}, +v14 = { + "kind": "ScalarField", + "alias": null, + "name": "url", + "args": null, + "storageKey": null +}, +v15 = { "kind": "ScalarField", "alias": null, "name": "authorAssociation", @@ -245,6 +263,7 @@ return { (v5/*: any*/), (v6/*: any*/), (v7/*: any*/), + (v8/*: any*/), { "kind": "LinkedField", "alias": null, @@ -254,14 +273,15 @@ return { "concreteType": null, "plural": false, "selections": [ - (v8/*: any*/), - (v9/*: any*/) + (v9/*: any*/), + (v10/*: any*/) ] }, - (v10/*: any*/), (v11/*: any*/), (v12/*: any*/), (v13/*: any*/), + (v14/*: any*/), + (v15/*: any*/), { "kind": "FragmentSpread", "name": "emojiReactionsController_reactable", @@ -313,6 +333,7 @@ return { (v5/*: any*/), (v6/*: any*/), (v7/*: any*/), + (v8/*: any*/), { "kind": "LinkedField", "alias": null, @@ -329,15 +350,16 @@ return { "args": null, "storageKey": null }, - (v8/*: any*/), (v9/*: any*/), + (v10/*: any*/), (v3/*: any*/) ] }, - (v10/*: any*/), (v11/*: any*/), (v12/*: any*/), (v13/*: any*/), + (v14/*: any*/), + (v15/*: any*/), { "kind": "LinkedField", "alias": null, @@ -393,11 +415,11 @@ return { "operationKind": "mutation", "name": "addPrReviewCommentMutation", "id": null, - "text": "mutation addPrReviewCommentMutation(\n $input: AddPullRequestReviewCommentInput!\n) {\n addPullRequestReviewComment(input: $input) {\n commentEdge {\n node {\n id\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n bodyHTML\n isMinimized\n viewerCanReact\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "mutation addPrReviewCommentMutation(\n $input: AddPullRequestReviewCommentInput!\n) {\n addPullRequestReviewComment(input: $input) {\n commentEdge {\n node {\n id\n author {\n __typename\n avatarUrl\n login\n ... on Node {\n id\n }\n }\n body\n bodyHTML\n isMinimized\n viewerCanReact\n viewerCanUpdate\n path\n position\n createdAt\n lastEditedAt\n url\n authorAssociation\n ...emojiReactionsController_reactable\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; })(); // prettier-ignore -(node/*: any*/).hash = '75ec864a015eb9def27a9f6fcd181c83'; +(node/*: any*/).hash = '0485900371928de8c6b843560dfe441c'; module.exports = node; diff --git a/lib/mutations/__generated__/addPrReviewMutation.graphql.js b/lib/mutations/__generated__/addPrReviewMutation.graphql.js index 6f617762f9..b11d90861f 100644 --- a/lib/mutations/__generated__/addPrReviewMutation.graphql.js +++ b/lib/mutations/__generated__/addPrReviewMutation.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash 7307f4d80765c6cfa54e21823c6b8e91 + * @relayHash 4efdc36d8dc992dc727d9021a1a10601 */ /* eslint-disable */ @@ -33,9 +33,12 @@ export type addPrReviewMutationResponse = {| +reviewEdge: ?{| +node: ?{| +id: string, + +body: string, +bodyHTML: any, +state: PullRequestReviewState, +submittedAt: ?any, + +viewerCanReact: boolean, + +viewerCanUpdate: boolean, +author: ?{| +login: string, +avatarUrl: any, @@ -60,9 +63,12 @@ mutation addPrReviewMutation( reviewEdge { node { id + body bodyHTML state submittedAt + viewerCanReact + viewerCanUpdate author { __typename login @@ -122,32 +128,53 @@ v2 = { v3 = { "kind": "ScalarField", "alias": null, - "name": "bodyHTML", + "name": "body", "args": null, "storageKey": null }, v4 = { "kind": "ScalarField", "alias": null, - "name": "state", + "name": "bodyHTML", "args": null, "storageKey": null }, v5 = { "kind": "ScalarField", "alias": null, - "name": "submittedAt", + "name": "state", "args": null, "storageKey": null }, v6 = { "kind": "ScalarField", "alias": null, - "name": "login", + "name": "submittedAt", "args": null, "storageKey": null }, v7 = { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanReact", + "args": null, + "storageKey": null +}, +v8 = { + "kind": "ScalarField", + "alias": null, + "name": "viewerCanUpdate", + "args": null, + "storageKey": null +}, +v9 = { + "kind": "ScalarField", + "alias": null, + "name": "login", + "args": null, + "storageKey": null +}, +v10 = { "kind": "ScalarField", "alias": null, "name": "avatarUrl", @@ -194,6 +221,9 @@ return { (v3/*: any*/), (v4/*: any*/), (v5/*: any*/), + (v6/*: any*/), + (v7/*: any*/), + (v8/*: any*/), { "kind": "LinkedField", "alias": null, @@ -203,8 +233,8 @@ return { "concreteType": null, "plural": false, "selections": [ - (v6/*: any*/), - (v7/*: any*/) + (v9/*: any*/), + (v10/*: any*/) ] }, { @@ -256,6 +286,9 @@ return { (v3/*: any*/), (v4/*: any*/), (v5/*: any*/), + (v6/*: any*/), + (v7/*: any*/), + (v8/*: any*/), { "kind": "LinkedField", "alias": null, @@ -272,8 +305,8 @@ return { "args": null, "storageKey": null }, - (v6/*: any*/), - (v7/*: any*/), + (v9/*: any*/), + (v10/*: any*/), (v2/*: any*/) ] }, @@ -319,13 +352,6 @@ return { ] } ] - }, - { - "kind": "ScalarField", - "alias": null, - "name": "viewerCanReact", - "args": null, - "storageKey": null } ] } @@ -339,11 +365,11 @@ return { "operationKind": "mutation", "name": "addPrReviewMutation", "id": null, - "text": "mutation addPrReviewMutation(\n $input: AddPullRequestReviewInput!\n) {\n addPullRequestReview(input: $input) {\n reviewEdge {\n node {\n id\n bodyHTML\n state\n submittedAt\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n ...emojiReactionsController_reactable\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", + "text": "mutation addPrReviewMutation(\n $input: AddPullRequestReviewInput!\n) {\n addPullRequestReview(input: $input) {\n reviewEdge {\n node {\n id\n body\n bodyHTML\n state\n submittedAt\n viewerCanReact\n viewerCanUpdate\n author {\n __typename\n login\n avatarUrl\n ... on Node {\n id\n }\n }\n ...emojiReactionsController_reactable\n }\n }\n }\n}\n\nfragment emojiReactionsController_reactable on Reactable {\n id\n ...emojiReactionsView_reactable\n}\n\nfragment emojiReactionsView_reactable on Reactable {\n id\n reactionGroups {\n content\n viewerHasReacted\n users {\n totalCount\n }\n }\n viewerCanReact\n}\n", "metadata": {} } }; })(); // prettier-ignore -(node/*: any*/).hash = '765a0aef6c6805d1733e99f53db0e82b'; +(node/*: any*/).hash = 'd2960bba4729b6c3e91e249ea582fec1'; module.exports = node; diff --git a/lib/mutations/add-pr-review-comment.js b/lib/mutations/add-pr-review-comment.js index 959013c127..e27db2642f 100644 --- a/lib/mutations/add-pr-review-comment.js +++ b/lib/mutations/add-pr-review-comment.js @@ -4,6 +4,8 @@ import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; import moment from 'moment'; +import {renderMarkdown} from '../helpers'; + const mutation = graphql` mutation addPrReviewCommentMutation($input: AddPullRequestReviewCommentInput!) { addPullRequestReviewComment(input: $input) { @@ -14,9 +16,11 @@ const mutation = graphql` avatarUrl login } + body bodyHTML isMinimized viewerCanReact + viewerCanUpdate path position createdAt @@ -57,10 +61,12 @@ export default (environment, {body, inReplyTo, reviewID, threadID, viewerID, pat const id = `add-pr-review-comment:comment:${placeholderID++}`; const comment = store.create(id, 'PullRequestReviewComment'); comment.setValue(id, 'id'); - comment.setValue(`${body}`, 'bodyHTML'); + comment.setValue(body, 'body'); + comment.setValue(renderMarkdown(body), 'bodyHTML'); comment.setValue(false, 'isMinimized'); comment.setValue(false, 'viewerCanMinimize'); comment.setValue(false, 'viewerCanReact'); + comment.setValue(false, 'viewerCanUpdate'); comment.setValue(moment().toISOString(), 'createdAt'); comment.setValue(null, 'lastEditedAt'); comment.setValue('NONE', 'authorAssociation'); diff --git a/lib/mutations/add-pr-review.js b/lib/mutations/add-pr-review.js index 41631f4c6a..44ad116dac 100644 --- a/lib/mutations/add-pr-review.js +++ b/lib/mutations/add-pr-review.js @@ -3,15 +3,20 @@ import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; +import {renderMarkdown} from '../helpers'; + const mutation = graphql` mutation addPrReviewMutation($input: AddPullRequestReviewInput!) { addPullRequestReview(input: $input) { reviewEdge { node { id + body bodyHTML state submittedAt + viewerCanReact + viewerCanUpdate author { login avatarUrl @@ -54,8 +59,11 @@ export default (environment, {body, event, pullRequestID, viewerID}) => { const review = store.create(id, 'PullRequestReview'); review.setValue(id, 'id'); review.setValue('PENDING', 'state'); - review.setValue(body || '...', 'bodyHTML'); + review.setValue(body, 'body'); + review.setValue(body ? renderMarkdown(body) : '...', 'bodyHTML'); review.setLinkedRecords([], 'reactionGroups'); + review.setValue(false, 'viewerCanReact'); + review.setValue(false, 'viewerCanUpdate'); let author; if (viewerID) { From 191b1d51c2044a326c689b7ad5997dc58295cfc9 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 13 May 2019 10:45:26 -0400 Subject: [PATCH 87/90] ReviewCommentView tests --- test/views/review-comment-view.test.js | 163 +++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 test/views/review-comment-view.test.js diff --git a/test/views/review-comment-view.test.js b/test/views/review-comment-view.test.js new file mode 100644 index 0000000000..69626c8825 --- /dev/null +++ b/test/views/review-comment-view.test.js @@ -0,0 +1,163 @@ +import React from 'react'; +import {shallow} from 'enzyme'; + +import ReviewCommentView from '../../lib/views/review-comment-view'; +import ActionableReviewView from '../../lib/views/actionable-review-view'; +import EmojiReactionsController from '../../lib/controllers/emoji-reactions-controller'; +import {GHOST_USER} from '../../lib/helpers'; + +describe('ReviewCommentView', function() { + let atomEnv; + + beforeEach(function() { + atomEnv = global.buildAtomEnvironment(); + }); + + afterEach(function() { + atomEnv.destroy(); + }); + + function buildApp(override = {}) { + const props = { + comment: {}, + isPosting: false, + confirm: () => {}, + tooltips: atomEnv.tooltips, + commands: atomEnv.commands, + renderEditedLink: () =>
, + renderAuthorAssociation: () =>
, + openIssueish: () => {}, + openIssueishLinkInNewTab: () => {}, + updateComment: () => {}, + reportMutationErrors: () => {}, + ...override, + }; + + return ; + } + + it('passes most props through to an ActionableReviewView', function() { + const comment = {id: 'comment0'}; + const confirm = () => {}; + const updateComment = () => {}; + + const wrapper = shallow(buildApp({ + comment, + isPosting: true, + confirm, + updateComment, + })); + + const arv = wrapper.find(ActionableReviewView); + assert.strictEqual(arv.prop('originalContent'), comment); + assert.isTrue(arv.prop('isPosting')); + assert.strictEqual(arv.prop('confirm'), confirm); + assert.strictEqual(arv.prop('contentUpdater'), updateComment); + }); + + describe('review comment data for non-edit mode', function() { + it('renders a placeholder message for minimized comments', function() { + const comment = { + id: 'comment0', + isMinimized: true, + }; + const showActionsMenu = sinon.spy(); + + const wrapper = shallow(buildApp({comment})) + .find(ActionableReviewView) + .renderProp('render')(showActionsMenu); + + assert.isTrue(wrapper.exists('.github-Review-comment--hidden')); + }); + + it('renders review comment data for non-edit mode', function() { + const comment = { + id: 'comment0', + isMinimized: false, + state: 'SUBMITTED', + author: { + login: 'me', + url: 'https://github.com/me', + avatarUrl: 'https://avatars.r.us/1234', + }, + createdAt: '2019-01-01T10:00:00Z', + bodyHTML: '

hi

', + }; + const showActionsMenu = sinon.spy(); + + const wrapper = shallow(buildApp({ + comment, + renderEditedLink: c => { + assert.strictEqual(c, comment); + return
; + }, + renderAuthorAssociation: c => { + assert.strictEqual(c, comment); + return
; + }, + })) + .find(ActionableReviewView) + .renderProp('render')(showActionsMenu); + + assert.isTrue(wrapper.exists('.github-Review-comment')); + assert.isFalse(wrapper.exists('.github-Review-comment--pending')); + assert.strictEqual(wrapper.find('.github-Review-avatar').prop('src'), comment.author.avatarUrl); + assert.strictEqual(wrapper.find('.github-Review-username').prop('href'), comment.author.url); + assert.strictEqual(wrapper.find('.github-Review-username').text(), comment.author.login); + assert.strictEqual(wrapper.find('Timeago').prop('time'), comment.createdAt); + assert.isTrue(wrapper.exists('.renderEditedLink')); + assert.isTrue(wrapper.exists('.renderAuthorAssociation')); + + wrapper.find('Octicon[icon="ellipses"]').simulate('click'); + assert.isTrue(showActionsMenu.calledWith(sinon.match.any, comment, comment.author)); + + assert.strictEqual(wrapper.find('GithubDotcomMarkdown').prop('html'), comment.bodyHTML); + assert.strictEqual(wrapper.find(EmojiReactionsController).prop('reactable'), comment); + }); + + it('uses a ghost user for comments with no author', function() { + const comment = { + id: 'comment0', + isMinimized: false, + state: 'SUBMITTED', + createdAt: '2019-01-01T10:00:00Z', + bodyHTML: '

hi

', + }; + const showActionsMenu = sinon.spy(); + + const wrapper = shallow(buildApp({comment})) + .find(ActionableReviewView) + .renderProp('render')(showActionsMenu); + + assert.isTrue(wrapper.exists('.github-Review-comment')); + assert.strictEqual(wrapper.find('.github-Review-avatar').prop('src'), GHOST_USER.avatarUrl); + assert.strictEqual(wrapper.find('.github-Review-username').prop('href'), GHOST_USER.url); + assert.strictEqual(wrapper.find('.github-Review-username').text(), GHOST_USER.login); + + wrapper.find('Octicon[icon="ellipses"]').simulate('click'); + assert.isTrue(showActionsMenu.calledWith(sinon.match.any, comment, GHOST_USER)); + }); + + it('includes a badge to mark pending comments', function() { + const comment = { + id: 'comment0', + isMinimized: false, + state: 'PENDING', + author: { + login: 'me', + url: 'https://github.com/me', + avatarUrl: 'https://avatars.r.us/1234', + }, + createdAt: '2019-01-01T10:00:00Z', + bodyHTML: '

hi

', + }; + + const wrapper = shallow(buildApp({comment})) + .find(ActionableReviewView) + .renderProp('render')(() => {}); + + assert.isTrue(wrapper.exists('.github-Review-comment--pending')); + assert.isTrue(wrapper.exists('.github-Review-pendingBadge')); + }); + }); +}); From b6e251fe3a898b32c4d96cbc8ae34c447d3526de Mon Sep 17 00:00:00 2001 From: Vanessa Yuen Date: Mon, 13 May 2019 17:25:59 +0200 Subject: [PATCH 88/90] fix the summary related tests and remove the comment ones --- test/views/reviews-view.test.js | 157 ++++++-------------------------- 1 file changed, 30 insertions(+), 127 deletions(-) diff --git a/test/views/reviews-view.test.js b/test/views/reviews-view.test.js index efacc4a504..ee2e13d41d 100644 --- a/test/views/reviews-view.test.js +++ b/test/views/reviews-view.test.js @@ -115,7 +115,7 @@ describe('ReviewsView', function() { assert.lengthOf(wrapper.find('details.github-Review'), 2); }); - it('displays ghost user information if author is null', function() { + it('displays ghost user information in review summary if author is null', function() { const {summaries, commentThreads} = aggregatedReviewsBuilder() .addReviewSummary(r => r.id(0)) .addReviewThread(t => t.addComment().addComment()) @@ -123,23 +123,14 @@ describe('ReviewsView', function() { const wrapper = shallow(buildApp({summaries, commentThreads})); + const showActionMenu = () => {}; + const summary = wrapper.find('.github-ReviewSummary').find('ActionableReviewView').renderProp('render')(showActionMenu); + // summary - assert.strictEqual(wrapper.find('.github-ReviewSummary-username').text(), GHOST_USER.login); - assert.strictEqual(wrapper.find('.github-ReviewSummary-username').prop('href'), GHOST_USER.url); - assert.strictEqual(wrapper.find('.github-ReviewSummary-avatar').prop('src'), GHOST_USER.avatarUrl); - assert.strictEqual(wrapper.find('.github-ReviewSummary-avatar').prop('alt'), GHOST_USER.login); - - // root comment - assert.strictEqual(wrapper.find('.github-Review-username').at(0).text(), GHOST_USER.login); - assert.strictEqual(wrapper.find('.github-Review-username').at(0).prop('href'), GHOST_USER.url); - assert.strictEqual(wrapper.find('.github-Review-avatar').at(0).prop('src'), GHOST_USER.avatarUrl); - assert.strictEqual(wrapper.find('.github-Review-avatar').at(0).prop('alt'), GHOST_USER.login); - - // non-root comment - assert.strictEqual(wrapper.find('.github-Review-username').at(1).text(), GHOST_USER.login); - assert.strictEqual(wrapper.find('.github-Review-username').at(1).prop('href'), GHOST_USER.url); - assert.strictEqual(wrapper.find('.github-Review-avatar').at(1).prop('src'), GHOST_USER.avatarUrl); - assert.strictEqual(wrapper.find('.github-Review-avatar').at(1).prop('alt'), GHOST_USER.login); + assert.strictEqual(summary.find('.github-ReviewSummary-username').text(), GHOST_USER.login); + assert.strictEqual(summary.find('.github-ReviewSummary-username').prop('href'), GHOST_USER.url); + assert.strictEqual(summary.find('.github-ReviewSummary-avatar').prop('src'), GHOST_USER.avatarUrl); + assert.strictEqual(summary.find('.github-ReviewSummary-avatar').prop('alt'), GHOST_USER.login); }); it('displays an author association badge for review summaries', function() { @@ -153,45 +144,20 @@ describe('ReviewsView', function() { .addReviewSummary(r => r.id(6).authorAssociation('NONE')) .build(); + const showActionMenu = () => {}; const wrapper = shallow(buildApp({summaries, commentThreads})); - - const reviews = wrapper.find('.github-ReviewSummary'); - assert.lengthOf(reviews, 7); - assert.strictEqual(reviews.at(0).find('.github-Review-authorAssociationBadge').text(), 'Member'); - assert.strictEqual(reviews.at(1).find('.github-Review-authorAssociationBadge').text(), 'Owner'); - assert.strictEqual(reviews.at(2).find('.github-Review-authorAssociationBadge').text(), 'Collaborator'); - assert.strictEqual(reviews.at(3).find('.github-Review-authorAssociationBadge').text(), 'Contributor'); - assert.strictEqual(reviews.at(4).find('.github-Review-authorAssociationBadge').text(), 'First-time contributor'); - assert.strictEqual(reviews.at(5).find('.github-Review-authorAssociationBadge').text(), 'First-timer'); - assert.isFalse(reviews.at(6).exists('.github-Review-authorAssociationBadge')); - }); - - it('displays an author association badge for review thread comments', function() { - const {summaries, commentThreads} = aggregatedReviewsBuilder() - .addReviewSummary(r => r.id(0)) - .addReviewThread(t => { - t.thread(t0 => t0.id('abcd')); - t.addComment(c => c.id(0).authorAssociation('MEMBER')); - t.addComment(c => c.id(1).authorAssociation('OWNER')); - t.addComment(c => c.id(2).authorAssociation('COLLABORATOR')); - t.addComment(c => c.id(3).authorAssociation('CONTRIBUTOR')); - t.addComment(c => c.id(4).authorAssociation('FIRST_TIME_CONTRIBUTOR')); - t.addComment(c => c.id(5).authorAssociation('FIRST_TIMER')); - t.addComment(c => c.id(6).authorAssociation('NONE')); - }) - .build(); - - const wrapper = shallow(buildApp({summaries, commentThreads})); - - const comments = wrapper.find('.github-Review-comment'); - assert.lengthOf(comments, 7); - assert.strictEqual(comments.at(0).find('.github-Review-authorAssociationBadge').text(), 'Member'); - assert.strictEqual(comments.at(1).find('.github-Review-authorAssociationBadge').text(), 'Owner'); - assert.strictEqual(comments.at(2).find('.github-Review-authorAssociationBadge').text(), 'Collaborator'); - assert.strictEqual(comments.at(3).find('.github-Review-authorAssociationBadge').text(), 'Contributor'); - assert.strictEqual(comments.at(4).find('.github-Review-authorAssociationBadge').text(), 'First-time contributor'); - assert.strictEqual(comments.at(5).find('.github-Review-authorAssociationBadge').text(), 'First-timer'); - assert.isFalse(comments.at(6).exists('.github-Review-authorAssociationBadge')); + assert.lengthOf(wrapper.find('.github-ReviewSummary'), 7); + const reviews = wrapper.find('.github-ReviewSummary').map(review => + review.find('ActionableReviewView').renderProp('render')(showActionMenu), + ); + + assert.strictEqual(reviews[0].find('.github-Review-authorAssociationBadge').text(), 'Member'); + assert.strictEqual(reviews[1].find('.github-Review-authorAssociationBadge').text(), 'Owner'); + assert.strictEqual(reviews[2].find('.github-Review-authorAssociationBadge').text(), 'Collaborator'); + assert.strictEqual(reviews[3].find('.github-Review-authorAssociationBadge').text(), 'Contributor'); + assert.strictEqual(reviews[4].find('.github-Review-authorAssociationBadge').text(), 'First-time contributor'); + assert.strictEqual(reviews[5].find('.github-Review-authorAssociationBadge').text(), 'First-timer'); + assert.isFalse(reviews[6].exists('.github-Review-authorAssociationBadge')); }); it('calls openIssueish when clicking on an issueish link in a review summary', function() { @@ -204,11 +170,13 @@ describe('ReviewsView', function() { .build(); const wrapper = shallow(buildApp({openIssueish, summaries})); + const showActionMenu = () => {}; + const review = wrapper.find('ActionableReviewView').renderProp('render')(showActionMenu); - wrapper.find('GithubDotcomMarkdown').prop('switchToIssueish')('aaa', 'bbb', 123); + review.find('GithubDotcomMarkdown').prop('switchToIssueish')('aaa', 'bbb', 123); assert.isTrue(openIssueish.calledWith('aaa', 'bbb', 123)); - wrapper.find('GithubDotcomMarkdown').prop('openIssueishLinkInNewTab')({ + review.find('GithubDotcomMarkdown').prop('openIssueishLinkInNewTab')({ target: {dataset: {url: 'https://github.com/ccc/ddd/issues/654'}}, }); assert.isTrue(openIssueish.calledWith('ccc', 'ddd', 654)); @@ -308,15 +276,9 @@ describe('ReviewsView', function() { it('renders threads with comments', function() { const threads = wrapper.find('details.github-Review'); assert.lengthOf(threads, 3); - assert.lengthOf(threads.at(0).find('.github-Review-comment'), 2); - assert.lengthOf(threads.at(1).find('.github-Review-comment'), 2); - assert.lengthOf(threads.at(2).find('.github-Review-comment'), 1); - }); - - it('hides minimized comment content', function() { - const thread = wrapper.find('details.github-Review').at(0); - const comment = thread.find('.github-Review-comment--hidden'); - assert.strictEqual(comment.find('em').text(), 'This comment was hidden'); + assert.lengthOf(threads.at(0).find('ReviewCommentView'), 2); + assert.lengthOf(threads.at(1).find('ReviewCommentView'), 2); + assert.lengthOf(threads.at(2).find('ReviewCommentView'), 1); }); it('groups comments by their resolved status', function() { @@ -338,41 +300,15 @@ describe('ReviewsView', function() { .build(); wrapper.setProps({...updatedProps}); + const showActionMenu = () => {}; - const updatedSummary = wrapper.find('.github-ReviewSummary').at(0); + const updatedSummary = wrapper.find('.github-ReviewSummary').at(0).find('ActionableReviewView').renderProp('render')(showActionMenu); assert.isTrue(updatedSummary.exists('.github-Review-edited')); const editedWrapper = updatedSummary.find('a.github-Review-edited'); assert.strictEqual(editedWrapper.text(), 'edited'); assert.strictEqual(editedWrapper.prop('href'), commentUrl); }); - it('indicates that a thread comment has been edited', function() { - const comment = wrapper.find('details.github-Review').at(0).find('.github-Review-comment').at(0); - assert.isFalse(comment.exists('.github-Review-edited')); - - const commentUrl = 'https://github.com/atom/github/pull/1995#discussion_r272475592'; - const updatedProps = aggregatedReviewsBuilder() - .addReviewSummary(r => r.id(0)) - .addReviewThread(t => { - t.thread(t0 => t0.id('abcd')); - t.addComment(c => - c.id(0).path('dir/file0').position(10).bodyHTML('i have opinions.').author(a => a.login('user0').avatarUrl('user0.jpg')) - .lastEditedAt('2018-12-27T17:51:17Z').url(commentUrl), - ); - t.addComment(c => - c.id(1).path('file0').position(10).bodyHTML('i disagree.').author(a => a.login('user1').avatarUrl('user1.jpg')).isMinimized(true), - ); - }) - .build(); - - wrapper.setProps({...updatedProps}); - - const updatedComment = wrapper.find('details.github-Review').at(0).find('.github-Review-comment').at(0); - assert.isTrue(updatedComment.exists('.github-Review-edited')); - const editedWrapper = updatedComment.find('a.github-Review-edited'); - assert.strictEqual(editedWrapper.text(), 'edited'); - assert.strictEqual(editedWrapper.prop('href'), commentUrl); - }); }); describe('each thread', function() { @@ -405,18 +341,6 @@ describe('ReviewsView', function() { assert.isTrue(unresolveThread.called); }); - it('displays a pending badge when the comment is part of a pending review', function() { - const thread = wrapper.find('details.github-Review').at(1); - - const comment0 = thread.find('.github-Review-comment').at(0); - assert.isFalse(comment0.hasClass('github-Review-comment--pending')); - assert.isFalse(comment0.exists('.github-Review-pendingBadge')); - - const comment1 = thread.find('.github-Review-comment').at(1); - assert.isTrue(comment1.hasClass('github-Review-comment--pending')); - assert.isTrue(comment1.exists('.github-Review-pendingBadge')); - }); - it('omits the / when there is no directory', function() { const thread = wrapper.find('details.github-Review').at(1); assert.isFalse(thread.exists('.github-Review-path')); @@ -489,15 +413,6 @@ describe('ReviewsView', function() { }); }); - it('each comment displays correct data', function() { - const comment = wrapper.find('.github-Review-comment').at(0); - assert.strictEqual(comment.find('.github-Review-avatar').prop('src'), 'user0.jpg'); - assert.strictEqual(comment.find('.github-Review-avatar').prop('alt'), 'user0'); - assert.strictEqual(comment.find('.github-Review-username').prop('href'), 'https://github.com/user0'); - assert.strictEqual(comment.find('.github-Review-username').text(), 'user0'); - assert.strictEqual(comment.find('GithubDotcomMarkdown').prop('html'), 'i have opinions.'); - }); - it('each comment displays reply button', function() { const submitSpy = sinon.spy(wrapper.instance(), 'submitReply'); const buttons = wrapper.find('.github-Review-replyButton'); @@ -538,18 +453,6 @@ describe('ReviewsView', function() { )); }); - it('handles issueish link clicks on comment bodies', function() { - const comment = wrapper.find('.github-Review-comment').at(2); - - comment.find('GithubDotcomMarkdown').prop('switchToIssueish')('aaa', 'bbb', 100); - assert.isTrue(openIssueish.calledWith('aaa', 'bbb', 100)); - - comment.find('GithubDotcomMarkdown').prop('openIssueishLinkInNewTab')({ - target: {dataset: {url: 'https://github.com/ccc/ddd/pulls/1'}}, - }); - assert.isTrue(openIssueish.calledWith('ccc', 'ddd', 1)); - }); - it('renders progress bar', function() { assert.isTrue(wrapper.find('.github-Reviews-progress').exists()); assert.strictEqual(wrapper.find('.github-Reviews-count').text(), 'Resolved 1 of 3'); From 9300c71a12bda6a2023b231de7564d17062139fb Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Tue, 14 May 2019 15:00:53 -0700 Subject: [PATCH 89/90] Finish converting `reportMutationErrors` to `reportRelayError` Co-Authored-By: Ash Wilson --- lib/controllers/reviews-controller.js | 4 ++-- lib/views/review-comment-view.js | 4 ++-- lib/views/reviews-view.js | 2 +- test/controllers/reviews-controller.test.js | 24 ++++++++++----------- test/views/review-comment-view.test.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/controllers/reviews-controller.js b/lib/controllers/reviews-controller.js index 5d325ee4be..1438f5baae 100644 --- a/lib/controllers/reviews-controller.js +++ b/lib/controllers/reviews-controller.js @@ -356,7 +356,7 @@ export class BareReviewsController extends React.Component { }); addEvent('update-review-comment', {package: 'github'}); } catch (error) { - this.props.reportMutationErrors('Unable to update comment', error); + this.props.reportRelayError('Unable to update comment', error); throw error; } } @@ -369,7 +369,7 @@ export class BareReviewsController extends React.Component { }); addEvent('update-review-summary', {package: 'github'}); } catch (error) { - this.props.reportMutationErrors('Unable to update review summary', error); + this.props.reportRelayError('Unable to update review summary', error); throw error; } } diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index d126ac6991..0096dbc3a8 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -29,7 +29,7 @@ export default class ReviewCommentView extends React.Component { openIssueish: PropTypes.func.isRequired, openIssueishLinkInNewTab: PropTypes.func.isRequired, updateComment: PropTypes.func.isRequired, - reportMutationErrors: PropTypes.func.isRequired, + reportRelayError: PropTypes.func.isRequired, } constructor(props) { @@ -98,7 +98,7 @@ export default class ReviewCommentView extends React.Component {
diff --git a/lib/views/reviews-view.js b/lib/views/reviews-view.js index a34766b7b8..3cad2e26ba 100644 --- a/lib/views/reviews-view.js +++ b/lib/views/reviews-view.js @@ -489,7 +489,7 @@ export default class ReviewsView extends React.Component { openIssueish={this.props.openIssueish} openIssueishLinkInNewTab={this.openIssueishLinkInNewTab} tooltips={this.props.tooltips} - reportMutationErrors={this.props.reportMutationErrors} + reportRelayError={this.props.reportRelayError} renderEditedLink={this.renderEditedLink} renderAuthorAssociation={this.renderAuthorAssociation} isPosting={isPosting} diff --git a/test/controllers/reviews-controller.test.js b/test/controllers/reviews-controller.test.js index f7512edacb..cfd6a4c65b 100644 --- a/test/controllers/reviews-controller.test.js +++ b/test/controllers/reviews-controller.test.js @@ -652,7 +652,7 @@ describe('ReviewsController', function() { describe('editing review comments', function() { it('calls the review comment update mutation and increments a metric', async function() { - const reportMutationErrors = sinon.spy(); + const reportRelayError = sinon.spy(); sinon.stub(reporterProxy, 'addEvent'); expectRelayQuery({ @@ -662,18 +662,18 @@ describe('ReviewsController', function() { }, }, op => relayResponseBuilder(op).build()).resolve(); - const wrapper = shallow(buildApp({reportMutationErrors})) + const wrapper = shallow(buildApp({reportRelayError})) .find(PullRequestCheckoutController) .renderProp('children')(noop); await wrapper.find(ReviewsView).prop('updateComment')('comment-0', 'new text'); - assert.isFalse(reportMutationErrors.called); + assert.isFalse(reportRelayError.called); assert.isTrue(reporterProxy.addEvent.calledWith('update-review-comment', {package: 'github'})); }); it('creates a notification and and re-throws the error if the comment cannot be updated', async function() { - const reportMutationErrors = sinon.spy(); + const reportRelayError = sinon.spy(); sinon.stub(reporterProxy, 'addEvent'); expectRelayQuery({ @@ -683,7 +683,7 @@ describe('ReviewsController', function() { }, }, op => relayResponseBuilder(op).addError('not right now').build()).resolve(); - const wrapper = shallow(buildApp({reportMutationErrors})) + const wrapper = shallow(buildApp({reportRelayError})) .find(PullRequestCheckoutController) .renderProp('children')(noop); @@ -691,14 +691,14 @@ describe('ReviewsController', function() { wrapper.find(ReviewsView).prop('updateComment')('comment-0', 'new text'), ); - assert.isTrue(reportMutationErrors.calledWith('Unable to update comment')); + assert.isTrue(reportRelayError.calledWith('Unable to update comment')); assert.isFalse(reporterProxy.addEvent.called); }); }); describe('editing review summaries', function() { it('calls the review summary update mutation and increments a metric', async function() { - const reportMutationErrors = sinon.spy(); + const reportRelayError = sinon.spy(); sinon.stub(reporterProxy, 'addEvent'); expectRelayQuery({ @@ -708,18 +708,18 @@ describe('ReviewsController', function() { }, }, op => relayResponseBuilder(op).build()).resolve(); - const wrapper = shallow(buildApp({reportMutationErrors})) + const wrapper = shallow(buildApp({reportRelayError})) .find(PullRequestCheckoutController) .renderProp('children')(noop); await wrapper.find(ReviewsView).prop('updateSummary')('review-0', 'stuff'); - assert.isFalse(reportMutationErrors.called); + assert.isFalse(reportRelayError.called); assert.isTrue(reporterProxy.addEvent.calledWith('update-review-summary', {package: 'github'})); }); it('creates a notification and and re-throws the error if the summary cannot be updated', async function() { - const reportMutationErrors = sinon.spy(); + const reportRelayError = sinon.spy(); sinon.stub(reporterProxy, 'addEvent'); expectRelayQuery({ @@ -729,7 +729,7 @@ describe('ReviewsController', function() { }, }, op => relayResponseBuilder(op).addError('not right now').build()).resolve(); - const wrapper = shallow(buildApp({reportMutationErrors})) + const wrapper = shallow(buildApp({reportRelayError})) .find(PullRequestCheckoutController) .renderProp('children')(noop); @@ -737,7 +737,7 @@ describe('ReviewsController', function() { wrapper.find(ReviewsView).prop('updateSummary')('review-0', 'stuff'), ); - assert.isTrue(reportMutationErrors.calledWith('Unable to update review summary')); + assert.isTrue(reportRelayError.calledWith('Unable to update review summary')); assert.isFalse(reporterProxy.addEvent.called); }); }); diff --git a/test/views/review-comment-view.test.js b/test/views/review-comment-view.test.js index 69626c8825..d0550d667f 100644 --- a/test/views/review-comment-view.test.js +++ b/test/views/review-comment-view.test.js @@ -29,7 +29,7 @@ describe('ReviewCommentView', function() { openIssueish: () => {}, openIssueishLinkInNewTab: () => {}, updateComment: () => {}, - reportMutationErrors: () => {}, + reportRelayError: () => {}, ...override, }; From 8e4b08fc53db2a30d588b4477edb1ed0ea019482 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Tue, 14 May 2019 19:06:51 -0500 Subject: [PATCH 90/90] Update lib/views/review-comment-view.js --- lib/views/review-comment-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/views/review-comment-view.js b/lib/views/review-comment-view.js index 0096dbc3a8..d68569857e 100644 --- a/lib/views/review-comment-view.js +++ b/lib/views/review-comment-view.js @@ -65,7 +65,7 @@ export default class ReviewCommentView extends React.Component { const author = comment.author || GHOST_USER; return ( -
+