diff --git a/plugins/github-pull-requests-board/src/api/useGetPullRequestDetails.ts b/plugins/github-pull-requests-board/src/api/useGetPullRequestDetails.ts index 05bbdc1e75..d44c36b54d 100644 --- a/plugins/github-pull-requests-board/src/api/useGetPullRequestDetails.ts +++ b/plugins/github-pull-requests-board/src/api/useGetPullRequestDetails.ts @@ -21,66 +21,71 @@ import { useOctokitGraphQl } from './useOctokitGraphQl'; export const useGetPullRequestDetails = () => { const graphql = useOctokitGraphQl>(); - const fn = React.useRef(async (repo: string, number: number): Promise => { - const [ organisation, repositoryName ] = repo.split('/'); + const fn = React.useRef( + async (repo: string, number: number): Promise => { + const [organisation, repositoryName] = repo.split('/'); - const { repository } = await graphql(` - query($name: String!, $owner: String!, $pull_number: Int!) { - repository(name: $name, owner: $owner) { - pullRequest(number: $pull_number) { - id - repository { - name - } - title - url - createdAt - lastEditedAt - latestReviews(first: 10) { - nodes { - author { - login - avatarUrl - ... on User { - id - email + const { repository } = await graphql( + ` + query ($name: String!, $owner: String!, $pull_number: Int!) { + repository(name: $name, owner: $owner) { + pullRequest(number: $pull_number) { + id + repository { name - login + } + title + url + createdAt + lastEditedAt + latestReviews(first: 10) { + nodes { + author { + login + avatarUrl + ... on User { + id + email + name + login + } + } + state + } + } + mergeable + state + reviewDecision + isDraft + createdAt + author { + ... on User { + id + email + avatarUrl + name + login + } + ... on Bot { + id + avatarUrl + login + } } } - state } } - mergeable - state - reviewDecision - isDraft - createdAt - author { - ... on User { - id - email - avatarUrl - name - login - } - ... on Bot { - id - avatarUrl - login - } - } - } - } - } - `, { - 'name': repositoryName, - 'owner': organisation, - 'pull_number': number - }); + `, + { + name: repositoryName, + owner: organisation, + pull_number: number, + }, + ); - return repository.pullRequest - }); + return repository.pullRequest; + }, + ); return fn.current; }; diff --git a/plugins/github-pull-requests-board/src/api/useGetPullRequestsFromRepository.ts b/plugins/github-pull-requests-board/src/api/useGetPullRequestsFromRepository.ts index 2dd19d8087..bd5df89833 100644 --- a/plugins/github-pull-requests-board/src/api/useGetPullRequestsFromRepository.ts +++ b/plugins/github-pull-requests-board/src/api/useGetPullRequestsFromRepository.ts @@ -19,30 +19,36 @@ import { GraphQlPullRequests, PullRequestsNumber } from '../utils/types'; import { useOctokitGraphQl } from './useOctokitGraphQl'; export const useGetPullRequestsFromRepository = () => { - const graphql = useOctokitGraphQl>(); + const graphql = + useOctokitGraphQl>(); - const fn = React.useRef(async (repo: string): Promise => { - const [ organisation, repositoryName ] = repo.split('/'); + const fn = React.useRef( + async (repo: string): Promise => { + const [organisation, repositoryName] = repo.split('/'); - const { repository } = await graphql(` - query($name: String!, $owner: String!) { - repository(name: $name, owner: $owner) { - pullRequests(states: OPEN, first: 10) { - edges { - node { - number + const { repository } = await graphql( + ` + query ($name: String!, $owner: String!) { + repository(name: $name, owner: $owner) { + pullRequests(states: OPEN, first: 10) { + edges { + node { + number + } + } + } } } - } - } - } - `, { - 'name': repositoryName, - 'owner': organisation, - }); + `, + { + name: repositoryName, + owner: organisation, + }, + ); - return repository.pullRequests.edges - }); + return repository.pullRequests.edges; + }, + ); return fn.current; }; diff --git a/plugins/github-pull-requests-board/src/api/useOctokitGraphQl.ts b/plugins/github-pull-requests-board/src/api/useOctokitGraphQl.ts index 91ce559ed2..a864f9950e 100644 --- a/plugins/github-pull-requests-board/src/api/useOctokitGraphQl.ts +++ b/plugins/github-pull-requests-board/src/api/useOctokitGraphQl.ts @@ -28,7 +28,7 @@ export const useOctokitGraphQl = () => { const config = useApi(configApiRef); const baseUrl = readGitHubIntegrationConfigs( - config.getOptionalConfigArray('providers.github') ?? [], + config.getOptionalConfigArray('integrations.github') ?? [], )[0].apiBaseUrl; return (path: string, options?: any): Promise => diff --git a/plugins/github-pull-requests-board/src/components/Card/Card.tsx b/plugins/github-pull-requests-board/src/components/Card/Card.tsx index 661416edbe..56e8c6a077 100644 --- a/plugins/github-pull-requests-board/src/components/Card/Card.tsx +++ b/plugins/github-pull-requests-board/src/components/Card/Card.tsx @@ -25,7 +25,7 @@ type Props = { authorName: string; authorAvatar?: string; repositoryName: string; -} +}; const Card: FunctionComponent = (props: PropsWithChildren) => { const { @@ -36,13 +36,13 @@ const Card: FunctionComponent = (props: PropsWithChildren) => { authorName, authorAvatar, repositoryName, - children + children, } = props; return ( - - + + { const { @@ -39,29 +39,26 @@ const CardHeader = (props: Props) => { return ( <> - - + + {repositoryName} - + {title} - - + + Created at: {getElapsedTime(createdAt)} - { - updatedAt && ( - - Last update: {getElapsedTime(updatedAt)} - - ) - } + {updatedAt && ( + + Last update: {getElapsedTime(updatedAt)} + + )} - ); }; diff --git a/plugins/github-pull-requests-board/src/components/InfoCardHeader/InfoCardHeader.tsx b/plugins/github-pull-requests-board/src/components/InfoCardHeader/InfoCardHeader.tsx index 47bab88693..9ba94dfa75 100644 --- a/plugins/github-pull-requests-board/src/components/InfoCardHeader/InfoCardHeader.tsx +++ b/plugins/github-pull-requests-board/src/components/InfoCardHeader/InfoCardHeader.tsx @@ -18,23 +18,23 @@ import { Typography, Box, IconButton } from '@material-ui/core'; import RefreshIcon from '@material-ui/icons/Refresh'; type Props = { - onRefresh: () => void; -} + onRefresh: () => void; +}; const InfoCardHeader = (props: PropsWithChildren) => { - const { children, onRefresh } = props; + const { children, onRefresh } = props; - return ( - - - Open pull requests - - - - - {children} - - ); + return ( + + + Open pull requests + + + + + {children} + + ); }; export default InfoCardHeader; diff --git a/plugins/github-pull-requests-board/src/components/PullRequestBoardOptions/PullRequestBoardOptions.tsx b/plugins/github-pull-requests-board/src/components/PullRequestBoardOptions/PullRequestBoardOptions.tsx index e914b774b3..6390b36aae 100644 --- a/plugins/github-pull-requests-board/src/components/PullRequestBoardOptions/PullRequestBoardOptions.tsx +++ b/plugins/github-pull-requests-board/src/components/PullRequestBoardOptions/PullRequestBoardOptions.tsx @@ -22,13 +22,13 @@ type Option = { icon: ReactNode; value: string; ariaLabel: string; -} +}; type Props = { value: string[]; onClickOption: (selectedOptions: PRCardFormating[]) => void; options: Option[]; -} +}; const PullRequestBoardOptions = (props: Props) => { const { value, onClickOption, options } = props; @@ -39,19 +39,20 @@ const PullRequestBoardOptions = (props: Props) => { onChange={(_event, selectedOptions) => onClickOption(selectedOptions)} aria-label="Pull Request board settings" > - { - options.map(({ icon, value: toggleValue, ariaLabel }, index) => ( - - - - {icon} - - - - )) - } + {options.map(({ icon, value: toggleValue, ariaLabel }, index) => ( + + + + {icon} + + + + ))} - ); }; diff --git a/plugins/github-pull-requests-board/src/components/PullRequestCard/PullRequestCard.tsx b/plugins/github-pull-requests-board/src/components/PullRequestCard/PullRequestCard.tsx index 2884f728d3..7e1596f5c2 100644 --- a/plugins/github-pull-requests-board/src/components/PullRequestCard/PullRequestCard.tsx +++ b/plugins/github-pull-requests-board/src/components/PullRequestCard/PullRequestCard.tsx @@ -14,7 +14,11 @@ * limitations under the License. */ import React, { FunctionComponent } from 'react'; -import { getApprovedReviews, getChangeRequests, getCommentedReviews } from '../../utils/functions'; +import { + getApprovedReviews, + getChangeRequests, + getCommentedReviews, +} from '../../utils/functions'; import { Reviews, Author } from '../../utils/types'; import { Card } from '../Card'; import { UserHeaderList } from '../UserHeaderList'; @@ -28,7 +32,7 @@ type Props = { reviews: Reviews; repositoryName: string; isDraft: boolean; -} +}; const PullRequestCard: FunctionComponent = (props: Props) => { const { @@ -59,16 +63,26 @@ const PullRequestCard: FunctionComponent = (props: Props) => { prUrl={url} > {!!approvedReviews.length && ( - reviewAuthor)} /> + reviewAuthor, + )} + /> )} {!!commentsReviews.length && ( reviewAuthor)} + label="💬" + users={commentsReviews.map( + ({ author: reviewAuthor }) => reviewAuthor, + )} /> )} {!!changeRequests.length && ( - reviewAuthor)} /> + reviewAuthor)} + /> )} ); diff --git a/plugins/github-pull-requests-board/src/components/TeamPullRequestsPage/index.ts b/plugins/github-pull-requests-board/src/components/TeamPullRequestsPage/index.ts index b58aed2482..b2f3619eaf 100644 --- a/plugins/github-pull-requests-board/src/components/TeamPullRequestsPage/index.ts +++ b/plugins/github-pull-requests-board/src/components/TeamPullRequestsPage/index.ts @@ -1 +1,16 @@ +/* + * Copyright 2022 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 { default as TeamPullRequestsPage } from './TeamPullRequestsPage'; diff --git a/plugins/github-pull-requests-board/src/components/UserHeader/UserHeader.tsx b/plugins/github-pull-requests-board/src/components/UserHeader/UserHeader.tsx index 7860994e31..f78ca44f66 100644 --- a/plugins/github-pull-requests-board/src/components/UserHeader/UserHeader.tsx +++ b/plugins/github-pull-requests-board/src/components/UserHeader/UserHeader.tsx @@ -14,24 +14,19 @@ * limitations under the License. */ import React from 'react'; -import { - Typography, - Box, - Avatar, - makeStyles -} from '@material-ui/core'; +import { Typography, Box, Avatar, makeStyles } from '@material-ui/core'; type Props = { name: string; avatar?: string; -} +}; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles(theme => ({ small: { width: theme.spacing(4), height: theme.spacing(4), - marginLeft: theme.spacing(1) - } + marginLeft: theme.spacing(1), + }, })); const UserHeader = (props: Props) => { @@ -39,8 +34,8 @@ const UserHeader = (props: Props) => { const classes = useStyles(); return ( - - + + {name} diff --git a/plugins/github-pull-requests-board/src/components/UserHeaderList/UserHeaderList.tsx b/plugins/github-pull-requests-board/src/components/UserHeaderList/UserHeaderList.tsx index 3faf2c519c..8bddeb7433 100644 --- a/plugins/github-pull-requests-board/src/components/UserHeaderList/UserHeaderList.tsx +++ b/plugins/github-pull-requests-board/src/components/UserHeaderList/UserHeaderList.tsx @@ -23,15 +23,23 @@ import { Author } from '../../utils/types'; type Props = { label?: string; users: Author[]; -} +}; const UserHeaderList = (props: Props) => { const { users, label } = props; return ( - - {label && {label}} - {filterSameUser(users).map(({ login, avatarUrl }) => )} + + {label && {label}} + {filterSameUser(users).map(({ login, avatarUrl }) => ( + + ))} ); }; diff --git a/plugins/github-pull-requests-board/src/components/Wrapper/Wrapper.tsx b/plugins/github-pull-requests-board/src/components/Wrapper/Wrapper.tsx index cb6e66fab8..18b47eafbf 100644 --- a/plugins/github-pull-requests-board/src/components/Wrapper/Wrapper.tsx +++ b/plugins/github-pull-requests-board/src/components/Wrapper/Wrapper.tsx @@ -18,18 +18,18 @@ import { Grid, Box } from '@material-ui/core'; type Props = { fullscreen: boolean; -} +}; const Wrapper = (props: PropsWithChildren) => { const { children, fullscreen } = props; return ( - + {children} - ) + ); }; export default Wrapper; diff --git a/plugins/github-pull-requests-board/src/hooks/usePullRequestsByTeam.tsx b/plugins/github-pull-requests-board/src/hooks/usePullRequestsByTeam.tsx index ce2636d5a2..57542d096d 100644 --- a/plugins/github-pull-requests-board/src/hooks/usePullRequestsByTeam.tsx +++ b/plugins/github-pull-requests-board/src/hooks/usePullRequestsByTeam.tsx @@ -25,39 +25,42 @@ export function usePullRequestsByTeam(repositories: string[]) { const getPullRequests = useGetPullRequestsFromRepository(); const getPullRequestDetails = useGetPullRequestDetails(); - const getPRsPerRepository = useCallback(async (repository: string): Promise => { + const getPRsPerRepository = useCallback( + async (repository: string): Promise => { + const pullRequestsNumbers = await getPullRequests(repository); - const pullRequestsNumbers = await getPullRequests(repository) + const pullRequestsWithDetails = await Promise.all( + pullRequestsNumbers.map(async ({ node }) => { + const pullRequest = await getPullRequestDetails( + repository, + node.number, + ); - const pullRequestsWithDetails = await Promise.all( - pullRequestsNumbers.map(async ({ node }) => { - const pullRequest = await getPullRequestDetails( - repository, - node.number, - ); + return pullRequest; + }), + ); - return pullRequest; - }), - ); - - return pullRequestsWithDetails; - }, [getPullRequests, getPullRequestDetails]); + return pullRequestsWithDetails; + }, + [getPullRequests, getPullRequestDetails], + ); const getPRsFromTeam = useCallback( async (teamRepositories: string[]): Promise => { - const teamRepositoriesPromises = teamRepositories.map(repository => getPRsPerRepository(repository), ); - const teamPullRequests = await Promise.allSettled(teamRepositoriesPromises) - .then(promises => promises.reduce((acc, curr) => { + const teamPullRequests = await Promise.allSettled( + teamRepositoriesPromises, + ).then(promises => + promises.reduce((acc, curr) => { if (curr.status === 'fulfilled') { return [...acc, ...curr.value]; } return acc; - }, [] as PullRequests) - ); + }, [] as PullRequests), + ); return teamPullRequests; }, @@ -70,11 +73,10 @@ export function usePullRequestsByTeam(repositories: string[]) { const teamPullRequests = await getPRsFromTeam(repositories); setPullRequests(formatPRsByReviewDecision(teamPullRequests)); setLoading(false); - }, [getPRsFromTeam, repositories]); useEffect(() => { - getAllPullRequests() + getAllPullRequests(); }, [getAllPullRequests]); return { diff --git a/plugins/github-pull-requests-board/src/hooks/useUserRepositories.tsx b/plugins/github-pull-requests-board/src/hooks/useUserRepositories.tsx index f974e7e457..68c4af96e4 100644 --- a/plugins/github-pull-requests-board/src/hooks/useUserRepositories.tsx +++ b/plugins/github-pull-requests-board/src/hooks/useUserRepositories.tsx @@ -33,14 +33,14 @@ export function useUserRepositories() { }); const entitiesNames: string[] = entitiesList.items.map(componentEntity => - getProjectNameFromEntity(componentEntity) + getProjectNameFromEntity(componentEntity), ); setRepositories([...new Set(entitiesNames)]); }, [catalogApi, teamEntity?.metadata?.name]); useEffect(() => { - getRepositoriesNames() + getRepositoriesNames(); }, [getRepositoriesNames]); return { diff --git a/plugins/github-pull-requests-board/src/plugin.ts b/plugins/github-pull-requests-board/src/plugin.ts index 8d45761def..e302d138fb 100644 --- a/plugins/github-pull-requests-board/src/plugin.ts +++ b/plugins/github-pull-requests-board/src/plugin.ts @@ -43,7 +43,9 @@ export const TeamPullRequestsPage = githubPullRequestsBoardPlugin.provide( createRoutableExtension({ name: 'PullRequestPage', component: () => - import('./components/TeamPullRequestsPage').then(m => m.TeamPullRequestsPage), + import('./components/TeamPullRequestsPage').then( + m => m.TeamPullRequestsPage, + ), mountPoint: rootRouteRef, }), ); diff --git a/plugins/github-pull-requests-board/src/utils/constants.ts b/plugins/github-pull-requests-board/src/utils/constants.ts index 22b23b259d..525fd9e1ce 100644 --- a/plugins/github-pull-requests-board/src/utils/constants.ts +++ b/plugins/github-pull-requests-board/src/utils/constants.ts @@ -14,7 +14,7 @@ * limitations under the License. */ export const COLUMNS = Object.freeze({ - REVIEW_REQUIRED: '🔍 Review required', - REVIEW_IN_PROGRESS: '📝 Review in progress', - APPROVED: '👍 Approved' -}) + REVIEW_REQUIRED: '🔍 Review required', + REVIEW_IN_PROGRESS: '📝 Review in progress', + APPROVED: '👍 Approved', +}); diff --git a/plugins/github-pull-requests-board/src/utils/types.tsx b/plugins/github-pull-requests-board/src/utils/types.tsx index b8ae1058f0..a2b121a1b8 100644 --- a/plugins/github-pull-requests-board/src/utils/types.tsx +++ b/plugins/github-pull-requests-board/src/utils/types.tsx @@ -15,31 +15,31 @@ */ export type GraphQlPullRequest = { repository: { - pullRequest: T - } -} + pullRequest: T; + }; +}; export type GraphQlPullRequests = { repository: { pullRequests: { - edges: T - } - } -} + edges: T; + }; + }; +}; export type PullRequestsNumber = { node: { number: number; - } -} + }; +}; export type Review = { state: - | 'PENDING' - | 'COMMENTED' - | 'APPROVED' - | 'CHANGES_REQUESTED' - | 'DISMISSED'; + | 'PENDING' + | 'COMMENTED' + | 'APPROVED' + | 'CHANGES_REQUESTED' + | 'DISMISSED'; author: Author; }; @@ -69,7 +69,7 @@ export type PullRequest = { reviewDecision: ReviewDecision | null; isDraft: boolean; createdAt: string; - author: Author + author: Author; }; export type PullRequests = PullRequest[]; @@ -81,4 +81,4 @@ export type PullRequestsColumn = { export type PRCardFormating = 'compacted' | 'fullscreen' | 'draft'; -export type ReviewDecision = 'IN_PROGRESS' | 'APPROVED' | 'REVIEW_REQUIRED' \ No newline at end of file +export type ReviewDecision = 'IN_PROGRESS' | 'APPROVED' | 'REVIEW_REQUIRED';