Merge pull request #8384 from marleypowell/marley/7678-pull-request-custom-filters
feat: Added ability to configure PR columns with parameters using filters.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops': patch
|
||||
'@backstage/plugin-azure-devops-backend': patch
|
||||
'@backstage/plugin-azure-devops-common': patch
|
||||
---
|
||||
|
||||
Created some initial filters that can be used to create pull request columns:
|
||||
|
||||
- All
|
||||
- AssignedToUser
|
||||
- AssignedToCurrentUser
|
||||
- AssignedToTeam
|
||||
- AssignedToTeams
|
||||
- AssignedToCurrentUsersTeams
|
||||
- CreatedByUser
|
||||
- CreatedByCurrentUser
|
||||
- CreatedByTeam
|
||||
- CreatedByTeams
|
||||
- CreatedByCurrentUsersTeams
|
||||
|
||||
Example custom column creation:
|
||||
|
||||
```tsx
|
||||
const COLUMN_CONFIGS: PullRequestColumnConfig[] = [
|
||||
{
|
||||
title: 'Created by me',
|
||||
filters: [{ type: FilterType.CreatedByCurrentUser }],
|
||||
},
|
||||
{
|
||||
title: 'Created by Backstage Core',
|
||||
filters: [
|
||||
{
|
||||
type: FilterType.CreatedByTeam,
|
||||
teamName: 'Backstage Core',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Assigned to my teams',
|
||||
filters: [{ type: FilterType.AssignedToCurrentUsersTeams }],
|
||||
},
|
||||
{
|
||||
title: 'Other PRs',
|
||||
filters: [{ type: FilterType.All }],
|
||||
simplified: true,
|
||||
},
|
||||
];
|
||||
|
||||
<Route
|
||||
path="/azure-pull-requests"
|
||||
element={
|
||||
<AzurePullRequestsPage
|
||||
projectName="{PROJECT_NAME}"
|
||||
defaultColumnConfigs={COLUMN_CONFIGS}
|
||||
/>
|
||||
}
|
||||
/>;
|
||||
```
|
||||
@@ -215,6 +215,7 @@ function convertReviewer(
|
||||
return {
|
||||
id: identityRef.id,
|
||||
displayName: identityRef.displayName,
|
||||
uniqueName: identityRef.uniqueName,
|
||||
imageUrl: getAvatarUrl(identityRef),
|
||||
isRequired: identityRef.isRequired,
|
||||
isContainer: identityRef.isContainer,
|
||||
|
||||
@@ -61,6 +61,10 @@ export interface CreatedBy {
|
||||
// (undocumented)
|
||||
imageUrl?: string;
|
||||
// (undocumented)
|
||||
teamIds?: string[];
|
||||
// (undocumented)
|
||||
teamNames?: string[];
|
||||
// (undocumented)
|
||||
uniqueName?: string;
|
||||
}
|
||||
|
||||
@@ -254,6 +258,8 @@ export interface Reviewer {
|
||||
// (undocumented)
|
||||
isRequired?: boolean;
|
||||
// (undocumented)
|
||||
uniqueName?: string;
|
||||
// (undocumented)
|
||||
voteStatus: PullRequestVoteStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ export interface DashboardPullRequest {
|
||||
export interface Reviewer {
|
||||
id?: string;
|
||||
displayName?: string;
|
||||
uniqueName?: string;
|
||||
imageUrl?: string;
|
||||
isRequired?: boolean;
|
||||
isContainer?: boolean;
|
||||
@@ -164,6 +165,8 @@ export interface CreatedBy {
|
||||
displayName?: string;
|
||||
uniqueName?: string;
|
||||
imageUrl?: string;
|
||||
teamIds?: string[];
|
||||
teamNames?: string[];
|
||||
}
|
||||
|
||||
export interface Repository {
|
||||
|
||||
@@ -6,9 +6,55 @@
|
||||
/// <reference types="react" />
|
||||
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { SvgIconProps } from '@material-ui/core';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AllFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type AllFilter = BaseFilter & {
|
||||
type: FilterType.All;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AssignedToTeamFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type AssignedToTeamFilter = BaseFilter & {
|
||||
type: FilterType.AssignedToTeam;
|
||||
teamId: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AssignedToTeamsFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type AssignedToTeamsFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.AssignedToTeams;
|
||||
teamIds: string[];
|
||||
}
|
||||
| {
|
||||
type: FilterType.AssignedToCurrentUsersTeams;
|
||||
teamIds?: string[];
|
||||
}
|
||||
);
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AssignedToUserFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type AssignedToUserFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.AssignedToUser;
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
type: FilterType.AssignedToCurrentUser;
|
||||
email?: string;
|
||||
}
|
||||
);
|
||||
|
||||
// Warning: (ae-missing-release-tag) "azureDevOpsPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
@@ -25,11 +71,71 @@ export const AzurePullRequestsIcon: (props: SvgIconProps) => JSX.Element;
|
||||
export const AzurePullRequestsPage: ({
|
||||
projectName,
|
||||
pollingInterval,
|
||||
defaultColumnConfigs,
|
||||
}: {
|
||||
projectName?: string | undefined;
|
||||
pollingInterval?: number | undefined;
|
||||
defaultColumnConfigs?: PullRequestColumnConfig[] | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "BaseFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type BaseFilter = {
|
||||
type: FilterType;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "CreatedByTeamFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type CreatedByTeamFilter = BaseFilter &
|
||||
({
|
||||
type: FilterType.CreatedByTeam;
|
||||
} & (
|
||||
| {
|
||||
teamId: string;
|
||||
}
|
||||
| {
|
||||
teamName: string;
|
||||
}
|
||||
));
|
||||
|
||||
// Warning: (ae-missing-release-tag) "CreatedByTeamsFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type CreatedByTeamsFilter = BaseFilter &
|
||||
(
|
||||
| ({
|
||||
type: FilterType.CreatedByTeams;
|
||||
} & (
|
||||
| {
|
||||
teamIds: string[];
|
||||
}
|
||||
| {
|
||||
teamNames: string[];
|
||||
}
|
||||
))
|
||||
| {
|
||||
type: FilterType.CreatedByCurrentUsersTeams;
|
||||
teamIds?: string[];
|
||||
}
|
||||
);
|
||||
|
||||
// Warning: (ae-missing-release-tag) "CreatedByUserFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type CreatedByUserFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.CreatedByUser;
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
type: FilterType.CreatedByCurrentUser;
|
||||
email?: string;
|
||||
}
|
||||
);
|
||||
|
||||
// Warning: (ae-missing-release-tag) "EntityAzurePipelinesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
@@ -48,10 +154,67 @@ export const EntityAzurePullRequestsContent: ({
|
||||
defaultLimit?: number | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "Filter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type Filter =
|
||||
| AssignedToUserFilter
|
||||
| CreatedByUserFilter
|
||||
| AssignedToTeamFilter
|
||||
| CreatedByTeamFilter
|
||||
| AssignedToTeamsFilter
|
||||
| CreatedByTeamsFilter
|
||||
| AllFilter;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "FilterType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export enum FilterType {
|
||||
// (undocumented)
|
||||
All = 'All',
|
||||
// (undocumented)
|
||||
AssignedToCurrentUser = 'AssignedToCurrentUser',
|
||||
// (undocumented)
|
||||
AssignedToCurrentUsersTeams = 'AssignedToCurrentUsersTeams',
|
||||
// (undocumented)
|
||||
AssignedToTeam = 'AssignedToTeam',
|
||||
// (undocumented)
|
||||
AssignedToTeams = 'AssignedToTeams',
|
||||
// (undocumented)
|
||||
AssignedToUser = 'AssignedToUser',
|
||||
// (undocumented)
|
||||
CreatedByCurrentUser = 'CreatedByCurrentUser',
|
||||
// (undocumented)
|
||||
CreatedByCurrentUsersTeams = 'CreatedByCurrentUsersTeams',
|
||||
// (undocumented)
|
||||
CreatedByTeam = 'CreatedByTeam',
|
||||
// (undocumented)
|
||||
CreatedByTeams = 'CreatedByTeams',
|
||||
// (undocumented)
|
||||
CreatedByUser = 'CreatedByUser',
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "isAzureDevOpsAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const isAzureDevOpsAvailable: (entity: Entity) => boolean;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "PullRequestColumnConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface PullRequestColumnConfig {
|
||||
// (undocumented)
|
||||
filters: Filter[];
|
||||
// (undocumented)
|
||||
simplified?: boolean;
|
||||
// (undocumented)
|
||||
title: string;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "PullRequestFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type PullRequestFilter = (pullRequest: DashboardPullRequest) => boolean;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -21,56 +21,17 @@ import {
|
||||
Progress,
|
||||
ResponseErrorPanel,
|
||||
} from '@backstage/core-components';
|
||||
import { PullRequestGroup, PullRequestGroupConfig } from './lib/types';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { getCreatedByUserFilter, getPullRequestGroups } from './lib/utils';
|
||||
import { useDashboardPullRequests, useUserEmail } from '../../hooks';
|
||||
import { PullRequestColumnConfig, PullRequestGroup } from './lib/types';
|
||||
import React, { useState } from 'react';
|
||||
import { getPullRequestGroupConfigs, getPullRequestGroups } from './lib/utils';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { FilterType } from './lib/filters';
|
||||
import { PullRequestGrid } from './lib/PullRequestGrid';
|
||||
|
||||
function usePullRequestGroupConfigs(
|
||||
userEmail: string | undefined,
|
||||
): PullRequestGroupConfig[] {
|
||||
const [pullRequestGroupConfigs, setPullRequestGroupConfigs] = useState<
|
||||
PullRequestGroupConfig[]
|
||||
>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const prGroupConfigs: PullRequestGroupConfig[] = [
|
||||
{ title: 'Created by me', filter: getCreatedByUserFilter(userEmail) },
|
||||
{ title: 'Other PRs', filter: _ => true, simplified: false },
|
||||
];
|
||||
|
||||
setPullRequestGroupConfigs(prGroupConfigs);
|
||||
}, [userEmail]);
|
||||
|
||||
return pullRequestGroupConfigs;
|
||||
}
|
||||
|
||||
function usePullRequestGroups(
|
||||
pullRequests: DashboardPullRequest[] | undefined,
|
||||
pullRequestGroupConfigs: PullRequestGroupConfig[],
|
||||
): PullRequestGroup[] {
|
||||
const [pullRequestGroups, setPullRequestGroups] = useState<
|
||||
PullRequestGroup[]
|
||||
>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (pullRequests) {
|
||||
const groups = getPullRequestGroups(
|
||||
pullRequests,
|
||||
pullRequestGroupConfigs,
|
||||
);
|
||||
setPullRequestGroups(groups);
|
||||
}
|
||||
}, [pullRequests, pullRequestGroupConfigs]);
|
||||
|
||||
return pullRequestGroups;
|
||||
}
|
||||
import { useDashboardPullRequests } from '../../hooks';
|
||||
import { useFilterProcessor } from './lib/hooks';
|
||||
|
||||
type PullRequestsPageContentProps = {
|
||||
pullRequestGroups: PullRequestGroup[];
|
||||
pullRequestGroups: PullRequestGroup[] | undefined;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
};
|
||||
@@ -80,7 +41,7 @@ const PullRequestsPageContent = ({
|
||||
loading,
|
||||
error,
|
||||
}: PullRequestsPageContentProps) => {
|
||||
if (loading && pullRequestGroups.length <= 0) {
|
||||
if (loading && (!pullRequestGroups || pullRequestGroups.length <= 0)) {
|
||||
return <Progress />;
|
||||
}
|
||||
|
||||
@@ -88,25 +49,50 @@ const PullRequestsPageContent = ({
|
||||
return <ResponseErrorPanel error={error} />;
|
||||
}
|
||||
|
||||
return <PullRequestGrid pullRequestGroups={pullRequestGroups} />;
|
||||
return <PullRequestGrid pullRequestGroups={pullRequestGroups ?? []} />;
|
||||
};
|
||||
|
||||
const DEFAULT_COLUMN_CONFIGS: PullRequestColumnConfig[] = [
|
||||
{
|
||||
title: 'Created by me',
|
||||
filters: [{ type: FilterType.CreatedByCurrentUser }],
|
||||
simplified: false,
|
||||
},
|
||||
{
|
||||
title: 'Other PRs',
|
||||
filters: [{ type: FilterType.All }],
|
||||
simplified: true,
|
||||
},
|
||||
];
|
||||
|
||||
type PullRequestsPageProps = {
|
||||
projectName?: string;
|
||||
pollingInterval?: number;
|
||||
defaultColumnConfigs?: PullRequestColumnConfig[];
|
||||
};
|
||||
|
||||
export const PullRequestsPage = ({
|
||||
projectName,
|
||||
pollingInterval,
|
||||
defaultColumnConfigs,
|
||||
}: PullRequestsPageProps) => {
|
||||
const { pullRequests, loading, error } = useDashboardPullRequests(
|
||||
projectName,
|
||||
pollingInterval,
|
||||
);
|
||||
const userEmail = useUserEmail();
|
||||
const pullRequestGroupConfigs = usePullRequestGroupConfigs(userEmail);
|
||||
const pullRequestGroups = usePullRequestGroups(
|
||||
|
||||
const [columnConfigs] = useState(
|
||||
defaultColumnConfigs ?? DEFAULT_COLUMN_CONFIGS,
|
||||
);
|
||||
|
||||
const filterProcessor = useFilterProcessor();
|
||||
|
||||
const pullRequestGroupConfigs = getPullRequestGroupConfigs(
|
||||
columnConfigs,
|
||||
filterProcessor,
|
||||
);
|
||||
|
||||
const pullRequestGroups = getPullRequestGroups(
|
||||
pullRequests,
|
||||
pullRequestGroupConfigs,
|
||||
);
|
||||
|
||||
@@ -15,3 +15,17 @@
|
||||
*/
|
||||
|
||||
export { PullRequestsPage } from './PullRequestsPage';
|
||||
export type { PullRequestColumnConfig } from './lib/types';
|
||||
export { FilterType } from './lib/filters';
|
||||
export type {
|
||||
BaseFilter,
|
||||
Filter,
|
||||
PullRequestFilter,
|
||||
AssignedToUserFilter,
|
||||
CreatedByUserFilter,
|
||||
AssignedToTeamFilter,
|
||||
CreatedByTeamFilter,
|
||||
AssignedToTeamsFilter,
|
||||
CreatedByTeamsFilter,
|
||||
AllFilter,
|
||||
} from './lib/filters';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
export type AllFilter = BaseFilter & {
|
||||
type: FilterType.All;
|
||||
};
|
||||
|
||||
export function createAllFilter(): PullRequestFilter {
|
||||
return (_pullRequest: DashboardPullRequest): boolean => true;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { stringArrayHas } from '../../../../utils';
|
||||
|
||||
export type AssignedToTeamFilter = BaseFilter & {
|
||||
type: FilterType.AssignedToTeam;
|
||||
teamId: string;
|
||||
};
|
||||
|
||||
export function createAssignedToTeamFilter(
|
||||
filter: AssignedToTeamFilter,
|
||||
): PullRequestFilter {
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
const reviewerIds = pullRequest.reviewers?.map(reviewer => reviewer.id);
|
||||
|
||||
if (!reviewerIds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return stringArrayHas(reviewerIds, filter.teamId, true);
|
||||
};
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { createAssignedToTeamFilter } from './assignedToTeamFilter';
|
||||
|
||||
export type AssignedToTeamsFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.AssignedToTeams;
|
||||
teamIds: string[];
|
||||
}
|
||||
| {
|
||||
type: FilterType.AssignedToCurrentUsersTeams;
|
||||
teamIds?: string[];
|
||||
}
|
||||
);
|
||||
|
||||
export function createAssignedToTeamsFilter(
|
||||
filter: AssignedToTeamsFilter,
|
||||
): PullRequestFilter {
|
||||
const teamIds = filter.teamIds;
|
||||
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
if (!teamIds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return teamIds.some(teamId => {
|
||||
return createAssignedToTeamFilter({
|
||||
type: FilterType.AssignedToTeam,
|
||||
teamId,
|
||||
})(pullRequest);
|
||||
});
|
||||
};
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { stringArrayHas } from '../../../../utils';
|
||||
|
||||
export type AssignedToUserFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.AssignedToUser;
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
type: FilterType.AssignedToCurrentUser;
|
||||
email?: string;
|
||||
}
|
||||
);
|
||||
|
||||
export function createAssignedToUserFilter(
|
||||
filter: AssignedToUserFilter,
|
||||
): PullRequestFilter {
|
||||
const email = filter.email;
|
||||
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
const uniqueNames = pullRequest.reviewers?.map(
|
||||
reviewer => reviewer.uniqueName,
|
||||
);
|
||||
|
||||
if (!email || !uniqueNames) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return stringArrayHas(uniqueNames, email, true);
|
||||
};
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Filter, FilterType } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { createFilter } from './createFilter';
|
||||
|
||||
describe('createFilter', () => {
|
||||
const pullRequest = {
|
||||
createdBy: {
|
||||
uniqueName: 'user1@backstage.com',
|
||||
teamIds: ['team1Id', 'team2Id'],
|
||||
},
|
||||
reviewers: [
|
||||
{ uniqueName: 'user2@backstage.com' },
|
||||
{ id: 'team2Id' },
|
||||
{ id: 'team3Id' },
|
||||
],
|
||||
} as DashboardPullRequest;
|
||||
|
||||
const testCases: Array<{ filter: Filter; result: boolean }> = [
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToUser,
|
||||
email: 'user2@backstage.com',
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToUser,
|
||||
email: 'random-user@backstage.com',
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByUser,
|
||||
email: 'user1@backstage.com',
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByUser,
|
||||
email: 'random-user@backstage.com',
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToTeam,
|
||||
teamId: 'team2Id',
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToTeam,
|
||||
teamId: 'randomTeamId',
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByTeam,
|
||||
teamId: 'team1Id',
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByTeam,
|
||||
teamId: 'randomTeamId',
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToTeams,
|
||||
teamIds: ['team2Id', 'randomTeamId'],
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToTeams,
|
||||
teamIds: ['team2Id', 'team3Id'],
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.AssignedToTeams,
|
||||
teamIds: ['randomTeam1Id', 'randomTeam2Id'],
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByTeams,
|
||||
teamIds: ['team1Id', 'randomTeamId'],
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByTeams,
|
||||
teamIds: ['team1Id', 'team2Id'],
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.CreatedByTeams,
|
||||
teamIds: ['randomTeam1Id', 'randomTeam2Id'],
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
filter: {
|
||||
type: FilterType.All,
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
];
|
||||
|
||||
testCases.forEach(({ filter, result }) => {
|
||||
it(`should return ${String(result)} when pull request ${
|
||||
result ? 'is' : 'is not'
|
||||
} ${filter.type}`, () => {
|
||||
const pullRequestFilter = createFilter(filter);
|
||||
expect(pullRequestFilter(pullRequest)).toBe(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Filter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { createAllFilter } from './allFilter';
|
||||
import { createAssignedToTeamFilter } from './assignedToTeamFilter';
|
||||
import { createAssignedToTeamsFilter } from './assignedToTeamsFilter';
|
||||
import { createAssignedToUserFilter } from './assignedToUserFilter';
|
||||
import { createCreatedByTeamFilter } from './createdByTeamFilter';
|
||||
import { createCreatedByTeamsFilter } from './createdByTeamsFilter';
|
||||
import { createCreatedByUserFilter } from './createdByUserFilter';
|
||||
|
||||
export function createFilter(filters: Filter | Filter[]): PullRequestFilter {
|
||||
const mapFilter = (filter: Filter): PullRequestFilter => {
|
||||
switch (filter.type) {
|
||||
case FilterType.AssignedToUser:
|
||||
case FilterType.AssignedToCurrentUser:
|
||||
return createAssignedToUserFilter(filter);
|
||||
|
||||
case FilterType.CreatedByUser:
|
||||
case FilterType.CreatedByCurrentUser:
|
||||
return createCreatedByUserFilter(filter);
|
||||
|
||||
case FilterType.AssignedToTeam:
|
||||
return createAssignedToTeamFilter(filter);
|
||||
|
||||
case FilterType.CreatedByTeam:
|
||||
return createCreatedByTeamFilter(filter);
|
||||
|
||||
case FilterType.AssignedToTeams:
|
||||
case FilterType.AssignedToCurrentUsersTeams:
|
||||
return createAssignedToTeamsFilter(filter);
|
||||
|
||||
case FilterType.CreatedByTeams:
|
||||
case FilterType.CreatedByCurrentUsersTeams:
|
||||
return createCreatedByTeamsFilter(filter);
|
||||
|
||||
case FilterType.All:
|
||||
return createAllFilter();
|
||||
|
||||
default:
|
||||
return _ => false;
|
||||
}
|
||||
};
|
||||
|
||||
if (Array.isArray(filters)) {
|
||||
if (filters.length === 1) {
|
||||
return mapFilter(filters[0]);
|
||||
}
|
||||
|
||||
return (pullRequest: DashboardPullRequest): boolean =>
|
||||
filters.every(filter => mapFilter(filter)(pullRequest));
|
||||
}
|
||||
|
||||
return mapFilter(filters);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { stringArrayHas } from '../../../../utils';
|
||||
|
||||
export type CreatedByTeamFilter = BaseFilter &
|
||||
({
|
||||
type: FilterType.CreatedByTeam;
|
||||
} & ({ teamId: string } | { teamName: string }));
|
||||
|
||||
export function createCreatedByTeamFilter(
|
||||
filter: CreatedByTeamFilter,
|
||||
): PullRequestFilter {
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
const [createdByTeams, team] =
|
||||
'teamId' in filter
|
||||
? [pullRequest.createdBy?.teamIds, filter.teamId]
|
||||
: [pullRequest.createdBy?.teamNames, filter.teamName];
|
||||
|
||||
if (!createdByTeams) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return stringArrayHas(createdByTeams, team, true);
|
||||
};
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { createCreatedByTeamFilter } from './createdByTeamFilter';
|
||||
|
||||
export type CreatedByTeamsFilter = BaseFilter &
|
||||
(
|
||||
| ({
|
||||
type: FilterType.CreatedByTeams;
|
||||
} & ({ teamIds: string[] } | { teamNames: string[] }))
|
||||
| {
|
||||
type: FilterType.CreatedByCurrentUsersTeams;
|
||||
teamIds?: string[];
|
||||
}
|
||||
);
|
||||
|
||||
export function createCreatedByTeamsFilter(
|
||||
filter: CreatedByTeamsFilter,
|
||||
): PullRequestFilter {
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
if ('teamNames' in filter) {
|
||||
const teamNames = filter.teamNames;
|
||||
|
||||
if (!teamNames) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return teamNames.some(teamName => {
|
||||
return createCreatedByTeamFilter({
|
||||
type: FilterType.CreatedByTeam,
|
||||
teamName,
|
||||
})(pullRequest);
|
||||
});
|
||||
}
|
||||
|
||||
const teamIds = filter.teamIds;
|
||||
|
||||
if (!teamIds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return teamIds.some(teamId => {
|
||||
return createCreatedByTeamFilter({
|
||||
type: FilterType.CreatedByTeam,
|
||||
teamId,
|
||||
})(pullRequest);
|
||||
});
|
||||
};
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseFilter, FilterType, PullRequestFilter } from './types';
|
||||
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { equalsIgnoreCase } from '../../../../utils';
|
||||
|
||||
export type CreatedByUserFilter = BaseFilter &
|
||||
(
|
||||
| {
|
||||
type: FilterType.CreatedByUser;
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
type: FilterType.CreatedByCurrentUser;
|
||||
email?: string;
|
||||
}
|
||||
);
|
||||
|
||||
export function createCreatedByUserFilter(
|
||||
filter: CreatedByUserFilter,
|
||||
): PullRequestFilter {
|
||||
const email = filter.email;
|
||||
|
||||
return (pullRequest: DashboardPullRequest): boolean => {
|
||||
const uniqueName = pullRequest.createdBy?.uniqueName;
|
||||
|
||||
if (!email || !uniqueName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return equalsIgnoreCase(email, uniqueName);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { createFilter } from './createFilter';
|
||||
export { FilterTypes, FilterType } from './types';
|
||||
export type {
|
||||
BaseFilter,
|
||||
Filter,
|
||||
PullRequestFilter,
|
||||
AssignedToUserFilter,
|
||||
CreatedByUserFilter,
|
||||
AssignedToTeamFilter,
|
||||
CreatedByTeamFilter,
|
||||
AssignedToTeamsFilter,
|
||||
CreatedByTeamsFilter,
|
||||
AllFilter,
|
||||
} from './types';
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AllFilter } from './allFilter';
|
||||
import { AssignedToTeamFilter } from './assignedToTeamFilter';
|
||||
import { AssignedToTeamsFilter } from './assignedToTeamsFilter';
|
||||
import { AssignedToUserFilter } from './assignedToUserFilter';
|
||||
import { CreatedByTeamFilter } from './createdByTeamFilter';
|
||||
import { CreatedByTeamsFilter } from './createdByTeamsFilter';
|
||||
import { CreatedByUserFilter } from './createdByUserFilter';
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
export enum FilterType {
|
||||
All = 'All',
|
||||
|
||||
// Assigned To
|
||||
AssignedToUser = 'AssignedToUser',
|
||||
AssignedToCurrentUser = 'AssignedToCurrentUser',
|
||||
AssignedToTeam = 'AssignedToTeam',
|
||||
AssignedToTeams = 'AssignedToTeams',
|
||||
AssignedToCurrentUsersTeams = 'AssignedToCurrentUsersTeams',
|
||||
|
||||
// Created By
|
||||
CreatedByUser = 'CreatedByUser',
|
||||
CreatedByCurrentUser = 'CreatedByCurrentUser',
|
||||
CreatedByTeam = 'CreatedByTeam',
|
||||
CreatedByTeams = 'CreatedByTeams',
|
||||
CreatedByCurrentUsersTeams = 'CreatedByCurrentUsersTeams',
|
||||
}
|
||||
|
||||
export const FilterTypes = [
|
||||
FilterType.All,
|
||||
|
||||
FilterType.AssignedToUser,
|
||||
FilterType.AssignedToCurrentUser,
|
||||
FilterType.AssignedToTeam,
|
||||
FilterType.AssignedToTeams,
|
||||
FilterType.AssignedToCurrentUsersTeams,
|
||||
|
||||
FilterType.CreatedByUser,
|
||||
FilterType.CreatedByCurrentUser,
|
||||
FilterType.CreatedByTeam,
|
||||
FilterType.CreatedByTeams,
|
||||
FilterType.CreatedByCurrentUsersTeams,
|
||||
] as const;
|
||||
|
||||
export type BaseFilter = {
|
||||
type: FilterType;
|
||||
};
|
||||
|
||||
export type Filter =
|
||||
| AssignedToUserFilter
|
||||
| CreatedByUserFilter
|
||||
| AssignedToTeamFilter
|
||||
| CreatedByTeamFilter
|
||||
| AssignedToTeamsFilter
|
||||
| CreatedByTeamsFilter
|
||||
| AllFilter;
|
||||
|
||||
export type {
|
||||
AssignedToUserFilter,
|
||||
CreatedByUserFilter,
|
||||
AssignedToTeamFilter,
|
||||
CreatedByTeamFilter,
|
||||
AssignedToTeamsFilter,
|
||||
CreatedByTeamsFilter,
|
||||
AllFilter,
|
||||
};
|
||||
|
||||
export type PullRequestFilter = (pullRequest: DashboardPullRequest) => boolean;
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './useFilterProcessor';
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Filter, FilterType } from '../filters';
|
||||
|
||||
import { useUserEmail } from '../../../../hooks';
|
||||
|
||||
export function useFilterProcessor(): (filters: Filter[]) => Filter[] {
|
||||
const userEmail = useUserEmail();
|
||||
|
||||
return (filters: Filter[]): Filter[] => {
|
||||
for (const filter of filters) {
|
||||
switch (filter.type) {
|
||||
case FilterType.AssignedToCurrentUser:
|
||||
case FilterType.CreatedByCurrentUser:
|
||||
filter.email = userEmail;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
};
|
||||
}
|
||||
@@ -14,23 +14,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
DashboardPullRequest,
|
||||
Team,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
import { Filter, PullRequestFilter } from './filters';
|
||||
|
||||
export interface PullRequestGroup {
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
export interface PullRequestColumnConfig {
|
||||
title: string;
|
||||
pullRequests: DashboardPullRequest[];
|
||||
filters: Filter[];
|
||||
simplified?: boolean;
|
||||
}
|
||||
|
||||
export type PullRequestFilter = (pullRequest: DashboardPullRequest) => boolean;
|
||||
|
||||
export type TeamFilter = (team: Team) => boolean;
|
||||
|
||||
export interface PullRequestGroupConfig {
|
||||
title: string;
|
||||
filter: PullRequestFilter;
|
||||
simplified?: boolean;
|
||||
}
|
||||
|
||||
export interface PullRequestGroup {
|
||||
title: string;
|
||||
pullRequests: DashboardPullRequest[];
|
||||
simplified?: boolean;
|
||||
}
|
||||
|
||||
@@ -19,33 +19,7 @@ import {
|
||||
PullRequestVoteStatus,
|
||||
Reviewer,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
import {
|
||||
arrayExtract,
|
||||
getCreatedByUserFilter,
|
||||
getPullRequestGroups,
|
||||
reviewerFilter,
|
||||
} from './utils';
|
||||
|
||||
describe('getCreatedByUserFilter', () => {
|
||||
it('should filter if pull request is created by user', () => {
|
||||
const userEmail = 'user1@backstage.com';
|
||||
const pr = {
|
||||
createdBy: { uniqueName: userEmail },
|
||||
} as DashboardPullRequest;
|
||||
const result = getCreatedByUserFilter(userEmail)(pr);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should not filter if pull request is not created by user', () => {
|
||||
const userEmail1 = 'user1@backstage.com';
|
||||
const userEmail2 = 'user2@backstage.com';
|
||||
const pr = {
|
||||
createdBy: { uniqueName: userEmail1 },
|
||||
} as DashboardPullRequest;
|
||||
const result = getCreatedByUserFilter(userEmail2)(pr);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
import { arrayExtract, getPullRequestGroups, reviewerFilter } from './utils';
|
||||
|
||||
describe('reviewerFilter', () => {
|
||||
it('should return false if reviewer has no vote and is not required', () => {
|
||||
@@ -128,11 +102,15 @@ describe('getPullRequestGroups', () => {
|
||||
];
|
||||
|
||||
const configs = [
|
||||
{ title: 'Created by me', filter: getCreatedByUserFilter(userEmail) },
|
||||
{
|
||||
title: 'Created by me',
|
||||
filter: (pullRequest: DashboardPullRequest): boolean =>
|
||||
pullRequest.createdBy?.uniqueName === userEmail,
|
||||
},
|
||||
{ title: 'Other PRs', filter: (_: unknown) => true, simplified: true },
|
||||
];
|
||||
|
||||
const result = getPullRequestGroups(pullRequests, configs);
|
||||
const result = getPullRequestGroups(pullRequests, configs) ?? [];
|
||||
|
||||
expect(result.length).toBe(2);
|
||||
|
||||
|
||||
@@ -19,25 +19,13 @@ import {
|
||||
PullRequestVoteStatus,
|
||||
Reviewer,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
import { Filter, createFilter } from './filters';
|
||||
import {
|
||||
PullRequestFilter,
|
||||
PullRequestColumnConfig,
|
||||
PullRequestGroup,
|
||||
PullRequestGroupConfig,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* Creates a filter that matches pull requests created by `userEmail`.
|
||||
* @param userEmail an email to filter by.
|
||||
* @returns a filter for pull requests created by `userEmail`.
|
||||
*/
|
||||
export function getCreatedByUserFilter(
|
||||
userEmail: string | undefined,
|
||||
): PullRequestFilter {
|
||||
return (pullRequest: DashboardPullRequest): boolean =>
|
||||
pullRequest.createdBy?.uniqueName?.toLocaleLowerCase() ===
|
||||
userEmail?.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a reviewer based on vote status and if the reviewer is required.
|
||||
* @param reviewer a reviewer to filter.
|
||||
@@ -97,9 +85,13 @@ export function arrayExtract<T>(arr: T[], filter: (value: T) => unknown): T[] {
|
||||
* @returns a list of pull request groups.
|
||||
*/
|
||||
export function getPullRequestGroups(
|
||||
pullRequests: DashboardPullRequest[],
|
||||
pullRequests: DashboardPullRequest[] | undefined,
|
||||
configs: PullRequestGroupConfig[],
|
||||
): PullRequestGroup[] {
|
||||
): PullRequestGroup[] | undefined {
|
||||
if (!pullRequests) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const remainingPullRequests: DashboardPullRequest[] = [...pullRequests];
|
||||
const pullRequestGroups: PullRequestGroup[] = [];
|
||||
|
||||
@@ -115,3 +107,17 @@ export function getPullRequestGroups(
|
||||
|
||||
return pullRequestGroups;
|
||||
}
|
||||
|
||||
export function getPullRequestGroupConfigs(
|
||||
columnConfigs: PullRequestColumnConfig[],
|
||||
filterProcessor: (filters: Filter[]) => Filter[],
|
||||
): PullRequestGroupConfig[] {
|
||||
return columnConfigs.map(columnConfig => {
|
||||
const filters = filterProcessor(columnConfig.filters);
|
||||
return {
|
||||
title: columnConfig.title,
|
||||
filter: createFilter(filters),
|
||||
simplified: columnConfig.simplified,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,3 +23,18 @@ export {
|
||||
} from './plugin';
|
||||
|
||||
export { AzurePullRequestsIcon } from './components/AzurePullRequestsIcon';
|
||||
|
||||
export { FilterType } from './components/PullRequestsPage';
|
||||
export type {
|
||||
PullRequestColumnConfig,
|
||||
BaseFilter,
|
||||
Filter,
|
||||
PullRequestFilter,
|
||||
AssignedToUserFilter,
|
||||
CreatedByUserFilter,
|
||||
AssignedToTeamFilter,
|
||||
CreatedByTeamFilter,
|
||||
AssignedToTeamsFilter,
|
||||
CreatedByTeamsFilter,
|
||||
AllFilter,
|
||||
} from './components/PullRequestsPage';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function arrayHas<T>(arr: T[], value: T): boolean {
|
||||
return new Set<T>(arr).has(value);
|
||||
}
|
||||
|
||||
export function stringArrayHas(
|
||||
arr: Array<string | undefined>,
|
||||
value: string | undefined,
|
||||
ignoreCase: boolean = false,
|
||||
): boolean {
|
||||
if (ignoreCase) {
|
||||
return arrayHas(
|
||||
arr.map(a => a?.toLocaleLowerCase('en-US')),
|
||||
value?.toLocaleLowerCase('en-US'),
|
||||
);
|
||||
}
|
||||
|
||||
return arrayHas(arr, value);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function equalsIgnoreCase(str1: string, str2: string): boolean {
|
||||
return str1.toLocaleLowerCase('en-US') === str2.toLocaleLowerCase('en-US');
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './arrayHas';
|
||||
export * from './equalsIgnoreCase';
|
||||
export * from './getDurationFromDates';
|
||||
Reference in New Issue
Block a user