Skip to content

Commit bf7fa05

Browse files
authored
Show review decision and reviewers in PR card
Review decisions and reviewers are not shown in PR card. Showing review decions and reviewers will allow users to see what needs to be done and which PRs require reviews at a glance, and showing reviewers allows tutors to gauge the level of PR reviews in the team. Displaying an icon for PRs that have been merged without reviews can help tutors to easily identify PRs that violate best practices for software engineering. Let's , * display review decions in the PR card, * display the GitHub avatars of PR reviewers in the PR card, * use tooltips to show information about reviews, and * display an icon for PRs that have been merged without any review.
1 parent 004311a commit bf7fa05

19 files changed

+264
-9
lines changed

graphql/fragments/issue-model.fragment.graphql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,17 @@ fragment issueModel on Issue {
2222
}
2323
}
2424
}
25+
2526
isDraft
27+
reviewDecision
28+
latestReviews(first: 100) {
29+
edges {
30+
node {
31+
state
32+
author {
33+
...reviewAuthor
34+
}
35+
}
36+
}
37+
}
2638
}

graphql/fragments/pullrequest.fragment.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ fragment pullrequest on PullRequest {
1313
milestone {
1414
...issueMilestone
1515
}
16+
reviewDecision
1617
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fragment reviewAuthor on Actor {
2+
login
3+
avatarUrl
4+
}

graphql/queries/fetch-pullrequests.graphql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ query FetchPullRequests($owner: String!, $name: String!, $cursor: String) {
2020
}
2121
}
2222
}
23+
latestReviews(first: 100) {
24+
edges {
25+
node {
26+
state #PENDING/COMMENTED/APPROVED/CHANGES_REQUESTED/DISMISSED
27+
author {
28+
...reviewAuthor
29+
}
30+
createdAt
31+
}
32+
}
33+
}
2334
}
2435
}
2536
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
extend type Issue {
22
isDraft: Boolean
3+
reviewDecision: String
4+
latestReviews(first: Int): PullRequestReviewConnection
35
}

src/app/core/models/github/github-graphql.issue-or-pr.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ export class GithubGraphqlIssueOrPr extends GithubIssue {
2121
assignees: flattenEdges(issue.assignees.edges),
2222
labels: flattenEdges(issue.labels.edges),
2323
milestone: issue.milestone ? issue.milestone : null,
24-
isDraft: issue.isDraft
24+
isDraft: issue.isDraft,
25+
reviewDecision: issue.reviewDecision,
26+
reviews: issue.latestReviews ? flattenEdges(issue.latestReviews.edges) : null
2527
});
2628
}
2729
}

src/app/core/models/github/github-issue.model.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { IssueState, IssueStateReason } from '../../../../../graphql/graphql-types';
2+
import { ReviewDecision } from '../issue.model';
3+
import { PullrequestReviewState } from '../pullrequest-review.model';
24
import { GithubComment } from './github-comment.model';
35
import { GithubLabel } from './github-label.model';
46

@@ -30,6 +32,16 @@ export class GithubIssue {
3032
issueOrPr?: string;
3133
isDraft: boolean;
3234

35+
reviews?: Array<{
36+
state: PullrequestReviewState;
37+
author: {
38+
login: string;
39+
avatarUrl: string;
40+
};
41+
}>;
42+
43+
reviewDecision?: ReviewDecision | null;
44+
3345
constructor(githubIssue: {}) {
3446
Object.assign(this, githubIssue);
3547
this.labels = [];

src/app/core/models/issue.model.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ import { GithubIssue } from './github/github-issue.model';
44
import { GithubLabel } from './github/github-label.model';
55
import { HiddenData } from './hidden-data.model';
66
import { Milestone } from './milestone.model';
7+
import { PullrequestReview } from './pullrequest-review.model';
8+
9+
export enum ReviewDecision {
10+
CHANGES_REQUESTED = 'CHANGES_REQUESTED',
11+
APPROVED = 'APPROVED',
12+
REVIEW_REQUIRED = 'REVIEW_REQUIRED'
13+
}
714

815
export class Issue {
916
/** Basic Fields */
@@ -28,6 +35,8 @@ export class Issue {
2835
assignees?: string[];
2936
labels?: string[];
3037
githubLabels?: GithubLabel[];
38+
reviews?: PullrequestReview[];
39+
reviewDecision?: ReviewDecision | null;
3140

3241
/**
3342
* Formats the text to create space at the end of the user input to prevent any issues with
@@ -88,6 +97,7 @@ export class Issue {
8897
this.author = githubIssue.user.login;
8998
// this.githubIssue = githubIssue;
9099
this.isDraft = githubIssue.isDraft;
100+
this.reviewDecision = githubIssue.reviewDecision;
91101

92102
this.assignees = githubIssue.assignees.map((assignee) => assignee.login);
93103
this.githubLabels = githubIssue.labels;
@@ -97,6 +107,8 @@ export class Issue {
97107
: this.issueOrPr === 'Issue'
98108
? Milestone.IssueWithoutMilestone
99109
: Milestone.PRWithoutMilestone;
110+
111+
this.reviews = githubIssue.reviews?.map((review) => new PullrequestReview(review));
100112
}
101113

102114
public static createPhaseBugReportingIssue(githubIssue: GithubIssue): Issue {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
export enum PullrequestReviewState {
2+
PENDING = 'PENDING',
3+
COMMENTED = 'COMMENTED',
4+
APPROVED = 'APPROVED',
5+
CHANGES_REQUESTED = 'CHANGES_REQUESTED',
6+
DISMISSED = 'DISMISSED'
7+
}
8+
9+
export class PullrequestReview {
10+
state: PullrequestReviewState;
11+
reviewer: string;
12+
avatarUrl: string;
13+
14+
constructor(prReview: { state: PullrequestReviewState; author: { login: string; avatarUrl: string } }) {
15+
this.state = prReview.state;
16+
this.reviewer = prReview.author.login;
17+
this.avatarUrl = prReview.author.avatarUrl;
18+
}
19+
20+
/**
21+
* Returns the required message to be shown in the tooltip for the review
22+
* @returns Tooltip message as a string
23+
*/
24+
public getReviewTooltipMessage(): string {
25+
switch (this.state) {
26+
case PullrequestReviewState.APPROVED:
27+
return `${this.reviewer} approved`;
28+
case PullrequestReviewState.CHANGES_REQUESTED:
29+
return `${this.reviewer} requested changes`;
30+
case PullrequestReviewState.COMMENTED:
31+
return `${this.reviewer} commented in a review`;
32+
case PullrequestReviewState.DISMISSED:
33+
return `${this.reviewer}'s review was dismissed`;
34+
case PullrequestReviewState.PENDING:
35+
return `${this.reviewer} has a pending review`;
36+
default:
37+
return '';
38+
}
39+
}
40+
}

src/app/shared/issue-pr-card/issue-pr-card-review-decision/issue-pr-card-review-decision.component.css

Whitespace-only changes.

0 commit comments

Comments
 (0)