diff --git a/plugins/azure-devops-common/src/types.ts b/plugins/azure-devops-common/src/types.ts
index eacc2af30d..458eaa76d4 100644
--- a/plugins/azure-devops-common/src/types.ts
+++ b/plugins/azure-devops-common/src/types.ts
@@ -126,3 +126,128 @@ export type PullRequestOptions = {
top: number;
status: PullRequestStatus;
};
+
+export interface DashboardPullRequest {
+ pullRequestId: number | undefined;
+ title: string | undefined;
+ description: string | undefined;
+ repository: Repository | undefined;
+ createdBy: CreatedBy | undefined;
+ hasAutoComplete: boolean;
+ policies: Policy[] | undefined;
+ reviewers: Reviewer[] | undefined;
+ creationDate: string | undefined;
+ status: PullRequestStatus | undefined;
+ isDraft: boolean | undefined;
+ link: string | undefined;
+}
+
+export interface Reviewer {
+ id: string | undefined;
+ displayName: string | undefined;
+ imageUrl: string | undefined;
+ isRequired: boolean | undefined;
+ isContainer: boolean | undefined;
+ voteStatus: PullRequestVoteStatus;
+}
+
+export interface Policy {
+ id: number | undefined;
+ type: PolicyType;
+ status: PolicyEvaluationStatus | undefined;
+ text: string | undefined;
+ link: string | undefined;
+}
+
+export interface CreatedBy {
+ id: string | undefined;
+ displayName: string | undefined;
+ uniqueName: string | undefined;
+ imageUrl: string | undefined;
+}
+
+export interface Repository {
+ id: string | undefined;
+ name: string | undefined;
+ url: string | undefined;
+}
+
+export interface Team {
+ id: string | undefined;
+ name: string | undefined;
+ memberIds: string[] | undefined;
+}
+
+/**
+ * Status of a policy which is running against a specific pull request.
+ */
+export enum PolicyEvaluationStatus {
+ /**
+ * The policy is either queued to run, or is waiting for some event before progressing.
+ */
+ Queued = 0,
+ /**
+ * The policy is currently running.
+ */
+ Running = 1,
+ /**
+ * The policy has been fulfilled for this pull request.
+ */
+ Approved = 2,
+ /**
+ * The policy has rejected this pull request.
+ */
+ Rejected = 3,
+ /**
+ * The policy does not apply to this pull request.
+ */
+ NotApplicable = 4,
+ /**
+ * The policy has encountered an unexpected error.
+ */
+ Broken = 5,
+}
+
+export enum PolicyType {
+ Build = 'Build',
+ Status = 'Status',
+ MinimumReviewers = 'MinimumReviewers',
+ Comments = 'Comments',
+ RequiredReviewers = 'RequiredReviewers',
+ MergeStrategy = 'MergeStrategy',
+}
+
+export const PolicyTypeId = {
+ /**
+ * This policy will require a successful build has been performed before updating protected refs.
+ */
+ Build: '0609b952-1397-4640-95ec-e00a01b2c241',
+ /**
+ * This policy will require a successful status to be posted before updating protected refs.
+ */
+ Status: 'cbdc66da-9728-4af8-aada-9a5a32e4a226',
+ /**
+ * This policy will ensure that a minimum number of reviewers have approved a pull request before completion.
+ */
+ MinimumReviewers: 'fa4e907d-c16b-4a4c-9dfa-4906e5d171dd',
+ /**
+ * Check if the pull request has any active comments.
+ */
+ Comments: 'c6a1889d-b943-4856-b76f-9e46bb6b0df2',
+ /**
+ * This policy will ensure that required reviewers are added for modified files matching specified patterns.
+ */
+ RequiredReviewers: 'fd2167ab-b0be-447a-8ec8-39368250530e',
+ /**
+ * This policy ensures that pull requests use a consistent merge strategy.
+ */
+ MergeStrategy: 'fa4e907d-c16b-4a4c-9dfa-4916e5d171ab',
+};
+
+export enum PullRequestVoteStatus {
+ Approved = 10,
+ ApprovedWithSuggestions = 5,
+ NoVote = 0,
+ WaitingForAuthor = -5,
+ Rejected = -10,
+}
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.stories.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.stories.tsx
index e918d37282..b948b616bd 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.stories.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.stories.tsx
@@ -14,10 +14,16 @@
* limitations under the License.
*/
+import {
+ DashboardPullRequest,
+ PolicyEvaluationStatus,
+ PolicyType,
+ PullRequestStatus,
+ PullRequestVoteStatus,
+} from '@backstage/plugin-azure-devops-common';
+
import { MemoryRouter } from 'react-router';
-import { PullRequest } from '../../../../api/types';
import { PullRequestCard } from './PullRequestCard';
-import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces';
import React from 'react';
export default {
@@ -25,16 +31,17 @@ export default {
component: PullRequestCard,
};
-const pullRequest: PullRequest = {
+const pullRequest: DashboardPullRequest = {
pullRequestId: 1,
title:
"feat(EXUX-4091): 🛂 Added the admin role authorization to the backend API's",
description:
'This PR contains the following updates:\n\n| Package | Type | Update | Change |\n|---|---|---|---|\n| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint) | devDependencies | major | [`4.33.0` -> `5.0.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/4.33.0/5.0.0) |\n| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescrip',
- link: '',
+ link: undefined,
repository: {
+ id: undefined,
name: 'backstage',
- url: '',
+ url: undefined,
},
createdBy: {
id: '',
@@ -44,31 +51,56 @@ const pullRequest: PullRequest = {
'https://dev.azure.com/exclaimerltd/_api/_common/identityImage?id=e6c0634b-68d2-6e6f-aa7d-adccada23216',
},
reviewers: [
- { displayName: 'Marley', imageUrl: '' },
- { displayName: 'User 1', imageUrl: '' },
- { displayName: 'User 2', imageUrl: '' },
+ {
+ id: undefined,
+ displayName: 'Marley',
+ imageUrl: '',
+ isRequired: true,
+ isContainer: false,
+ voteStatus: PullRequestVoteStatus.Approved,
+ },
+ {
+ id: undefined,
+ displayName: 'User 1',
+ imageUrl: '',
+ isRequired: false,
+ isContainer: false,
+ voteStatus: PullRequestVoteStatus.WaitingForAuthor,
+ },
+ {
+ id: undefined,
+ displayName: 'User 2',
+ imageUrl: '',
+ isRequired: true,
+ isContainer: false,
+ voteStatus: PullRequestVoteStatus.NoVote,
+ },
],
policies: [
{
- type: 'Build',
- status: 'Running',
+ id: undefined,
+ type: PolicyType.Build,
+ status: PolicyEvaluationStatus.Running,
text: 'Build: UI (running)',
+ link: undefined,
},
{
- type: 'MinimumReviewers',
+ id: undefined,
+ type: PolicyType.MinimumReviewers,
text: 'Minimum number of reviewers (2)',
- status: '',
+ status: undefined,
+ link: undefined,
},
{
- type: 'Comments',
+ id: undefined,
+ type: PolicyType.Comments,
text: 'Comment requirements',
- status: '',
+ status: undefined,
+ link: undefined,
},
],
hasAutoComplete: true,
creationDate: new Date(Date.now() - 10000000).toISOString(),
- sourceRefName: '',
- targetRefName: '',
status: PullRequestStatus.Active,
isDraft: false,
};
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.tsx
index 1d30504f44..cfb0a121db 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCard.tsx
@@ -18,8 +18,8 @@ import { Card, CardContent, CardHeader, Link } from '@material-ui/core';
import { AutoCompleteIcon } from '../AutoCompleteIcon';
import { Avatar } from '@backstage/core-components';
+import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
import { DateTime } from 'luxon';
-import { PullRequest } from '../../../../api/types';
import { PullRequestCardPolicies } from './PullRequestCardPolicies';
import { PullRequestCardReviewers } from './PullRequestCardReviewers';
import React from 'react';
@@ -53,7 +53,7 @@ const useStyles = makeStyles(
);
type PullRequestCardProps = {
- pullRequest: PullRequest;
+ pullRequest: DashboardPullRequest;
simplified?: boolean;
};
@@ -75,21 +75,23 @@ export const PullRequestCard = ({
const subheader = (
- {pullRequest.repository.name}
+ {pullRequest.repository?.name}
{' '}
- · {DateTime.fromISO(pullRequest.creationDate.toString()).toRelative()}
+ ·{' '}
+ {pullRequest.creationDate &&
+ DateTime.fromISO(pullRequest.creationDate).toRelative()}
);
const avatar = (
);
@@ -97,7 +99,10 @@ export const PullRequestCard = ({
const classes = useStyles();
return (
-
+
-
+ {pullRequest.policies && (
+
+ )}
-
+ {pullRequest.reviewers && (
+
+ )}
)}
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicies.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicies.tsx
index eeb78b32f8..21fe7ba034 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicies.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicies.tsx
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+import {
+ Policy,
+ PolicyEvaluationStatus,
+ PolicyType,
+} from '@backstage/plugin-azure-devops-common';
import {
PolicyInProgressIcon,
PolicyIssueIcon,
@@ -21,25 +26,24 @@ import {
PullRequestCardPolicy,
} from './PullRequestCardPolicy';
-import { Policy } from '../../../../api/types';
import React from 'react';
function getPullRequestCardPolicy(policy: Policy): JSX.Element | null {
switch (policy.type) {
- case 'Build':
+ case PolicyType.Build:
switch (policy.status) {
- case 'Running':
+ case PolicyEvaluationStatus.Running:
return (
}
/>
);
- case 'Rejected':
+ case PolicyEvaluationStatus.Rejected:
return (
} />
);
- case 'Queued':
+ case PolicyEvaluationStatus.Queued:
return (
} />
);
- case 'Status':
- case 'Comments':
+ case PolicyType.Status:
+ case PolicyType.Comments:
return (
} />
);
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicy.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicy.tsx
index 479c31f8c1..22f9bca39b 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicy.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardPolicy.tsx
@@ -18,7 +18,7 @@ import { styled, withStyles } from '@material-ui/core/styles';
import CancelIcon from '@material-ui/icons/Cancel';
import GroupWorkIcon from '@material-ui/icons/GroupWork';
-import { Policy } from '../../../../api/types';
+import { Policy } from '@backstage/plugin-azure-devops-common';
import React from 'react';
import WatchLaterIcon from '@material-ui/icons/WatchLater';
@@ -57,7 +57,7 @@ const PullRequestCardPolicyContainer = styled('div')({
type PullRequestCardPolicyProps = {
policy: Policy;
- icon: React.ReactNode;
+ icon: JSX.Element;
};
export const PullRequestCardPolicy = ({
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewer.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewer.tsx
index 87dbb6118b..1d2049728b 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewer.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewer.tsx
@@ -16,8 +16,7 @@
import { Avatar } from '@backstage/core-components';
import React from 'react';
-import { Reviewer } from '../../../../api/types';
-import { Tooltip } from '@material-ui/core';
+import { Reviewer } from '@backstage/plugin-azure-devops-common';
type PullRequestCardReviewerProps = {
reviewer: Reviewer;
@@ -26,16 +25,14 @@ type PullRequestCardReviewerProps = {
export const PullRequestCardReviewer = ({
reviewer,
}: PullRequestCardReviewerProps) => (
-
-
-
+
);
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewers.tsx b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewers.tsx
index b46223e0cb..a3b87e0439 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewers.tsx
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/PullRequestCard/PullRequestCardReviewers.tsx
@@ -14,9 +14,13 @@
* limitations under the License.
*/
+import {
+ PullRequestVoteStatus,
+ Reviewer,
+} from '@backstage/plugin-azure-devops-common';
+
import { PullRequestCardReviewer } from './PullRequestCardReviewer';
import React from 'react';
-import { Reviewer } from '../../../../api/types';
import { styled } from '@material-ui/core/styles';
const PullRequestCardReviewersContainer = styled('div')({
@@ -34,8 +38,14 @@ export const PullRequestCardReviewers = ({
reviewers,
}: PullRequestCardReviewersProps) => (
- {reviewers.map(reviewer => (
+ {reviewers.filter(reviewerFilter).map(reviewer => (
))}
);
+
+function reviewerFilter(reviewer: Reviewer): boolean {
+ return reviewer.voteStatus === PullRequestVoteStatus.NoVote
+ ? !!reviewer.isRequired
+ : !reviewer.isContainer;
+}
diff --git a/plugins/azure-devops/src/components/PullRequestsPage/lib/types.ts b/plugins/azure-devops/src/components/PullRequestsPage/lib/types.ts
index f05e036a58..2d936f7b64 100644
--- a/plugins/azure-devops/src/components/PullRequestsPage/lib/types.ts
+++ b/plugins/azure-devops/src/components/PullRequestsPage/lib/types.ts
@@ -14,10 +14,23 @@
* limitations under the License.
*/
-import { PullRequest } from '../../../api/types';
+import {
+ DashboardPullRequest,
+ Team,
+} from '@backstage/plugin-azure-devops-common';
export interface PullRequestGroup {
title: string;
- pullRequests: PullRequest[];
+ pullRequests: DashboardPullRequest[];
+ simplified?: boolean;
+}
+
+export type PullRequestFilter = (pullRequest: DashboardPullRequest) => boolean;
+
+export type TeamFilter = (team: Team) => boolean;
+
+export interface PullRequestGroupConfig {
+ title: string;
+ filter: PullRequestFilter;
simplified?: boolean;
}