From fd99dbb8772ec26e5b5147f8949b2c7879b4ecb8 Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Tue, 9 Apr 2024 15:16:36 -0600 Subject: [PATCH 1/5] feat: [code-1625]: add changes for overview panel --- .../ReviewSplitButton/ReviewSplitButton.tsx | 8 +- .../ExecutionStatus/ExecutionStatus.tsx | 2 +- web/src/framework/strings/stringTypes.ts | 56 ++ web/src/hooks/useGetImportProgress.tsx | 12 + web/src/hooks/usePRChecksDecision3.tsx | 158 ++++++ web/src/i18n/strings.en.yaml | 69 ++- web/src/icons/code-fail.svg | 1 + web/src/icons/code-success.svg | 1 + web/src/icons/code-timeout.svg | 1 + web/src/icons/emptyStatus.svg | 1 + web/src/icons/greyCircle.svg | 1 + web/src/pages/PullRequest/Checks/Checks.tsx | 2 +- .../CodeOwners/CodeOwnersOverview.tsx | 24 +- .../PullRequest/Conversation/Conversation.tsx | 35 +- .../MergeSideDialogBox.tsx | 237 ++++++++ .../PullRequestActionsBox.module.scss | 65 ++- .../PullRequestActionsBox.module.scss.d.ts | 9 + .../PullRequestActionsBox.tsx | 261 ++++----- .../PullRequestOverviewPanel.module.scss | 125 ++++ .../PullRequestOverviewPanel.module.scss.d.ts | 37 ++ .../PullRequestOverviewPanel.tsx | 197 +++++++ .../PullRequestPanelSections.tsx | 21 + .../sections/ChangesSection.tsx | 536 ++++++++++++++++++ .../sections/ChecksSection.tsx | 368 ++++++++++++ .../sections/CommentsSection.tsx | 62 ++ .../sections/MergeSection.tsx | 60 ++ .../sections/PullRequestTopSection.tsx | 0 .../pages/PullRequest/PullRequestUtils.tsx | 7 + web/src/services/code/index.tsx | 2 + web/src/utils/Utils.ts | 142 ++++- 30 files changed, 2292 insertions(+), 208 deletions(-) create mode 100644 web/src/hooks/useGetImportProgress.tsx create mode 100644 web/src/hooks/usePRChecksDecision3.tsx create mode 100644 web/src/icons/code-fail.svg create mode 100644 web/src/icons/code-success.svg create mode 100644 web/src/icons/code-timeout.svg create mode 100644 web/src/icons/emptyStatus.svg create mode 100644 web/src/icons/greyCircle.svg create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestActionsBox/MergeSideDialogBox.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.module.scss create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.module.scss.d.ts create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestPanelSections.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/ChangesSection.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/ChecksSection.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/CommentsSection.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/MergeSection.tsx create mode 100644 web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/PullRequestTopSection.tsx diff --git a/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx b/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx index 15219d606..1e41960ef 100644 --- a/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx +++ b/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx @@ -26,7 +26,7 @@ import { useAppContext } from 'AppContext' import { useStrings } from 'framework/strings' import type { EnumPullReqReviewDecision, TypesPullReq } from 'services/code' import type { GitInfoProps } from 'utils/GitUtils' -import { getErrorMessage } from 'utils/Utils' +import { ApproveState, getErrorMessage } from 'utils/Utils' import css from '../Changes.module.scss' interface PrReviewOption { @@ -37,12 +37,6 @@ interface PrReviewOption { color: Color } -enum ApproveState { - APPROVED = 'approved', - CHANGEREQ = 'changereq', - APPROVE = 'approve', - OUTDATED = 'outdated' -} interface ReviewSplitButtonProps extends Pick { shouldHide: boolean pullRequestMetadata?: TypesPullReq diff --git a/web/src/components/ExecutionStatus/ExecutionStatus.tsx b/web/src/components/ExecutionStatus/ExecutionStatus.tsx index a26da0cf0..b4d96669d 100644 --- a/web/src/components/ExecutionStatus/ExecutionStatus.tsx +++ b/web/src/components/ExecutionStatus/ExecutionStatus.tsx @@ -80,7 +80,7 @@ export const ExecutionStatus: React.FC = ({ title: getString('failed').toLocaleUpperCase() }, [ExecutionState.FAILURE]: { - icon: 'error-transparent-no-outline', + icon: 'warning-icon', css: css.failure, title: getString('failed').toLocaleUpperCase() }, diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index 12c858bbf..7f6b97bf2 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -25,7 +25,9 @@ export interface StringsMap { all: string allBranches: string allComments: string + allCommentsResolved: string allCommits: string + allConflictsNeedToBeResolved: string alreadyHaveAccount: string and: string applyChanges: string @@ -137,8 +139,44 @@ export interface StringsMap { changeRole: string changedSinceLastView: string changes: string + 'changesSection.approvalPending': string + 'changesSection.changesAppByRev': string + 'changesSection.changesApproved': string + 'changesSection.changesApprovedByXReviewers': string + 'changesSection.changesWereAppByCodeOwner': string + 'changesSection.changesWereAppByLatestReqRev': string + 'changesSection.codeOwnerReqChanges': string + 'changesSection.codeOwnerReqChangesToPr': string + 'changesSection.latestChangesApprovedByXReviewers': string + 'changesSection.latestChangesPendingReqRev': string + 'changesSection.latestChangesWereAppByCodeOwner': string + 'changesSection.latestChangesWereApprovedByReq': string + 'changesSection.noCodeOwnerReviewsReq': string + 'changesSection.noReviewsReq': string + 'changesSection.pendingAppFromCodeOwners': string + 'changesSection.pendingLatestApprovalCodeOwners': string + 'changesSection.pullReqWithoutAnyReviews': string + 'changesSection.reqChangeFromCodeOwners': string + 'changesSection.someChangesWereAppByCodeOwner': string + 'changesSection.waitingOnCodeOwner': string + 'changesSection.waitingOnLatestCodeOwner': string + 'changesSection.waitingOnReviewers': string + 'changesSection.xApprovalsArePending': string characterLimit: string checkRuns: string + 'checkSection.allChecksSucceeded': string + 'checkSection.allReqChecksPassed': string + 'checkSection.someChecksFailed': string + 'checkSection.someChecksNotComplete': string + 'checkSection.someChecksRunning': string + 'checkSection.someReqChecksFailed': string + 'checkSection.someReqChecksPending': string + 'checkSection.someReqChecksRunning': string + 'checkStatus.error': string + 'checkStatus.failed': string + 'checkStatus.pending': string + 'checkStatus.running': string + 'checkStatus.succeeded': string checkSuites: string checks: string clear: string @@ -150,6 +188,7 @@ export interface StringsMap { closed: string 'codeOwner.approvalCompleted': string 'codeOwner.changesRequested': string + 'codeOwner.pendingLatestApprovals': string 'codeOwner.title': string 'codeOwner.waitToApprove': string codeSearch: string @@ -218,12 +257,14 @@ export interface StringsMap { customMin: string customSecond: string customTime: string + customizeMergeCommitMessage: string dangerDeleteRepo: string defaultBranch: string defaultBranchTitle: string delete: string deleteBranch: string deleteBranchConfirm: string + deleteBranchText: string deleteCommentConfirm: string deleteFile: string deleteNotAllowed: string @@ -239,6 +280,7 @@ export interface StringsMap { deployKeys: string descending: string description: string + details: string diff: string disableWebhookContent: string disableWebhookTitle: string @@ -430,8 +472,12 @@ export interface StringsMap { makeRequired: string manageApiToken: string manageCredText: string + markAsDraft: string matchPassword: string + mergeCheckInProgress: string mergeCommit: string + mergeSetting: string + mergeStrategy: string merged: string minPassLimit: string missingPerms: string @@ -622,6 +668,7 @@ export interface StringsMap { 'pr.fileUnchanged': string 'pr.mergeOptions.close': string 'pr.mergeOptions.closeDesc': string + 'pr.mergeOptions.createAMergeCommit': string 'pr.mergeOptions.createMergeCommit': string 'pr.mergeOptions.createMergeCommitDesc': string 'pr.mergeOptions.rebaseAndMerge': string @@ -647,6 +694,7 @@ export interface StringsMap { 'pr.prStateChangedDraft': string 'pr.readyForReview': string 'pr.requestSubmitted': string + 'pr.requestedChanges': string 'pr.reviewChanges': string 'pr.reviewSubmitted': string 'pr.showDiff': string @@ -670,6 +718,7 @@ export interface StringsMap { 'prChecks.success': string 'prChecks.viewExternal': string prGenSummary: string + prHasNoConflicts: string prMustSelectSourceAndTargetBranches: string prSourceAndTargetMustBeDifferent: string 'prState.draftDesc': string @@ -730,6 +779,7 @@ export interface StringsMap { required: string resetZoom: string resolve: string + resolveComments: string resolved: string resolvedComments: string results: string @@ -780,6 +830,7 @@ export interface StringsMap { seeNMoreMatches: string selectBranchPlaceHolder: string selectLanguagePlaceholder: string + selectMergeStrat: string selectRange: string selectRepositoryPlaceholder: string selectSpace: string @@ -791,11 +842,14 @@ export interface StringsMap { setAsAdmin: string setting: string settings: string + showCheckAll: string showCommitHistory: string showEverything: string showLess: string + showLessCheck: string showLessMatches: string showMore: string + showMoreText: string showNMoreMatches: string signIn: string signUp: string @@ -901,6 +955,7 @@ export interface StringsMap { 'validation.uidInvalid': string 'validation.uidRequired': string value: string + view: string viewAllBranches: string viewAllTags: string viewCommitDetails: string @@ -940,6 +995,7 @@ export interface StringsMap { webhooks: string whatsNew: string write: string + writeDownCommit: string yourBranches: string yours: string zoomIn: string diff --git a/web/src/hooks/useGetImportProgress.tsx b/web/src/hooks/useGetImportProgress.tsx new file mode 100644 index 000000000..1ef00c72a --- /dev/null +++ b/web/src/hooks/useGetImportProgress.tsx @@ -0,0 +1,12 @@ +import { useGet } from 'restful-react' +import type { TypesRepository } from 'services/code' + +export function useGetImportProgress(repo: TypesRepository) { + const { data: importStatus, loading } = useGet({ + path: `/api/v1/repos/${repo.path}/+/import-progress`, + lazy: !repo.importing + }) + // const { data: importStatus, loading } = { data: {}, loading: false } + + return { importStatus, loading } +} diff --git a/web/src/hooks/usePRChecksDecision3.tsx b/web/src/hooks/usePRChecksDecision3.tsx new file mode 100644 index 000000000..33f83887d --- /dev/null +++ b/web/src/hooks/usePRChecksDecision3.tsx @@ -0,0 +1,158 @@ +/* + * Copyright 2023 Harness, Inc. + * + * 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 { useEffect, useMemo, useState } from 'react' +import { stringSubstitute } from '@harnessio/uicore' +import { Color } from '@harnessio/design-system' +import { useGet } from 'restful-react' +import type { GitInfoProps } from 'utils/GitUtils' +import { useStrings } from 'framework/strings' +import type { TypesCheck } from 'services/code' +import { ExecutionState } from 'components/ExecutionStatus/ExecutionStatus' + +interface PrTypeCheck { + required: boolean + bypassable: boolean + check: TypesCheck +} + +export function usePRChecksDecision({ + repoMetadata, + pullReqMetadata +}: Partial>) { + const { data, error, refetch } = useGet<{ checks: PrTypeCheck[]; commit_sha: string }>({ + path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullReqMetadata?.number}/checks`, + queryParams: { + debounce: 500 + } + }) + const [count, setCount] = useState(DEFAULT_COUNTS) + const { getString } = useStrings() + const [color, setColor] = useState(Color.GREEN_500) + const [background, setBackground] = useState(Color.GREEN_50) + const [message, setMessage] = useState('') + const [complete, setComplete] = useState(true) + const status = useMemo(() => { + let _status: ExecutionState | undefined + const _count = { ...DEFAULT_COUNTS } + const total = data?.checks?.length + + if (total) { + for (const check of data.checks) { + switch (check.check.status) { + case ExecutionState.ERROR: + case ExecutionState.FAILURE: + case ExecutionState.RUNNING: + case ExecutionState.PENDING: + case ExecutionState.SUCCESS: + _count[check.check.status]++ + setCount({ ..._count }) + break + default: + console.error('Unrecognized PR check status', check) // eslint-disable-line no-console + break + } + } + + if (_count.error) { + _status = ExecutionState.ERROR + setColor(Color.RED_900) + setBackground(Color.RED_50) + setMessage(stringSubstitute(getString('prChecks.error'), { count: _count.error, total }) as string) + } else if (_count.failure) { + _status = ExecutionState.FAILURE + setColor(Color.RED_900) + setBackground(Color.RED_50) + setMessage(stringSubstitute(getString('prChecks.failure'), { count: _count.failure, total }) as string) + } else if (_count.killed) { + _status = ExecutionState.KILLED + setColor(Color.RED_900) + setBackground(Color.RED_50) + setMessage(stringSubstitute(getString('prChecks.killed'), { count: _count.killed, total }) as string) + } else if (_count.running) { + _status = ExecutionState.RUNNING + setColor(Color.ORANGE_900) + setBackground(Color.ORANGE_100) + setMessage(stringSubstitute(getString('prChecks.running'), { count: _count.running, total }) as string) + } else if (_count.pending) { + _status = ExecutionState.PENDING + setColor(Color.GREY_600) + setBackground(Color.GREY_100) + setMessage(stringSubstitute(getString('prChecks.pending'), { count: _count.pending, total }) as string) + } else if (_count.skipped) { + _status = ExecutionState.SKIPPED + setColor(Color.GREY_600) + setBackground(Color.GREY_100) + setMessage(stringSubstitute(getString('prChecks.skipped'), { count: _count.skipped, total }) as string) + } else if (_count.success) { + _status = ExecutionState.SUCCESS + setColor(Color.GREEN_800) + setBackground(Color.GREEN_50) + setMessage(stringSubstitute(getString('prChecks.success'), { count: _count.success, total }) as string) + } + + setComplete(!_count.pending && !_count.running) + } else { + setComplete(false) + } + + return _status + }, [data]) // eslint-disable-line react-hooks/exhaustive-deps + + useEffect(() => { + let tornDown = false + const pollingFn = () => { + if (repoMetadata?.path && pullReqMetadata?.source_sha && !complete && !tornDown) { + // TODO: fix racing condition where an ongoing refetch of the old sha overwrites the new one. + // TEMPORARY SOLUTION: set debounce to 1 second to reduce likelyhood + refetch({ debounce: 1 }).then(() => { + if (!tornDown) { + interval = window.setTimeout(pollingFn, POLLING_INTERVAL) + } + }) + } + } + let interval = window.setTimeout(pollingFn, POLLING_INTERVAL) + return () => { + tornDown = true + window.clearTimeout(interval) + } + }, [repoMetadata?.path, pullReqMetadata?.source_sha, complete]) // eslint-disable-line react-hooks/exhaustive-deps + + return { + overallStatus: status, + count, + error, + data, + color, + background, + message + } +} + +export type PRChecksDecisionResult = ReturnType + +const POLLING_INTERVAL = 10000 + +const DEFAULT_COUNTS = { + error: 0, + failure: 0, + pending: 0, + running: 0, + success: 0, + skipped: 0, + killed: 0 +} diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index c2ab7f25b..6fd6aaeac 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -271,7 +271,7 @@ pr: unified: Unified reviewChanges: Review changes mergePR: Merge pull request - branchHasNoConflicts: This branch has no conflicts with the base branch + branchHasNoConflicts: Pull request can be merged checkingToMerge: Checking for ability to merge automatically... prCanBeMerged: Mergeing can be performed automatically. enterDesc: Enter description here @@ -284,6 +284,7 @@ pr: prClosed: This Pull Request was closed. reviewSubmitted: Review submitted. requestSubmitted: Request for changes submitted. + requestedChanges: '{{user}} requested changes to the pull request' prReviewSubmit: '{user} {state|approved:approved, rejected:rejected,changereq:requested changes to, reviewed} this pull request. {time}' prMergedBannerInfo: '{user} merged branch {source} into {target} {time}.' prMergedInfo: '{user} merged changes from {source} into {target} as {mergeSha} {time}' @@ -309,6 +310,7 @@ pr: rebaseAndMergeDesc: All commits from this branch will be rebased and added to the base branch. close: Close pull request closeDesc: Close this pull request. You can still re-open the request after closing. + createAMergeCommit: Create a merge commit outdated: Outdated titleIsRequired: Pull Request title is required. descIsRequired: Pull Request description is required. @@ -953,10 +955,10 @@ branchProtection: ruleCreated: Rule Created requirePr: Require pull request requirePrText: Do not allow any changes to matching branches without a pull request - prFailedText: 'This branch has no conflicts with the base branch. {{ruleCount}} branch rules failed' + prFailedText: 'Cannot merge pull request' mergePrAlertTitle: Merge pull request alert mergePrAlertText: 'Merge cannot be completed. {{ruleCount}} branch rules failed: ' - mergeCheckboxAlert: Bypass branch rules and merge + mergeCheckboxAlert: Bypass and merge anyway createBranchAlertBtn: Bypass rules and create branch createBranchAlertText: Some rules will be bypassed by creating branch createBranchBlockText: Some rules don't allow you to create branch @@ -974,6 +976,7 @@ codeOwner: changesRequested: '{count} {count|1:change,changes} requested' waitToApprove: '{count} pending {count|1:approval,approvals} ' approvalCompleted: '{count}/{total} approvals completed' + pendingLatestApprovals: '{count} approvals pending on latest changes' approved: Approved comingSoon: Coming soon... enterANumber: Enter a number @@ -1003,8 +1006,63 @@ customMin: '{{minutes}}m' customSecond: '{{seconds}}s' reqChanges: 'Request changes' summary: Summary -prGenSummary: AIDA generate PR summary, insert at the cursor or replace selected text only. -aidaGenSummary: 'AIDA is generating a summary...' +prGenSummary: Have Harness AIDA summarize the code changes in this pull request +aidaGenSummary: '[AIDA is generating a summary...]' +allCommentsResolved: All comments resolved +resolveComments: There are {{n}} unresolved comments +view: View +mergeCheckInProgress: Merge check in progress... +allConflictsNeedToBeResolved: All conflicts have to be resolved before merging +details: Details +showCheckAll: Show all checks +showLessCheck: Show less checks +markAsDraft: Mark as draft +mergeSetting: Merge setting +deleteBranchText: Delete the branch after merging +customizeMergeCommitMessage: Customize merge commit message +mergeStrategy: Merge strategy +selectMergeStrat: Select merge strategy +writeDownCommit: Write down commit message here +prHasNoConflicts: This branch has no conflicts with base branch +checkStatus: + succeeded: Succeeded in {time} + failed: Failed in {time} + running: Running... + pending: Pending... + error: Errored in {time} +changesSection: + reqChangeFromCodeOwners: Changes requested by code owner + codeOwnerReqChanges: Code owner requested changes + pendingAppFromCodeOwners: Approvals pending from code owners + pendingLatestApprovalCodeOwners: Latest changes are pending approval from code owners + waitingOnCodeOwner: Changes are pending approval from code owners + waitingOnReviewers: Changes are pending approval from required reviewers + waitingOnLatestCodeOwner: Waiting on code owner reviews of latest changes + approvalPending: Approvals pending + changesApproved: Changes approved + noReviewsReq: No reviews required + noCodeOwnerReviewsReq: No codeowner reviews + pullReqWithoutAnyReviews: Pull request can be merged without any reviews + changesAppByRev: Changes were approved by reviewers + changesApprovedByXReviewers: Changes were approved by {length} {length|1:reviewer,reviewers} + latestChangesApprovedByXReviewers: Latest changes were approved by {length} {length|1:reviewer,reviewers} + latestChangesWereAppByCodeOwner: Latest changes were approved by code owners + latestChangesPendingReqRev: Latest changes are pending approval from required reviewers + changesWereAppByCodeOwner: Changes were approved by code owners + changesWereAppByLatestReqRev: Changes were approved by required reviewers + latestChangesWereApprovedByReq: Latest changes were approved by required reviewers + someChangesWereAppByCodeOwner: Some changes were approved by code owners + xApprovalsArePending: '{approved}/{min} approvals are pending' + codeOwnerReqChangesToPr: Code owners requested changes to the pull request +checkSection: + someReqChecksFailed: Some required checks have failed + someReqChecksPending: Some required checks are pending + someReqChecksRunning: Some required checks are running + someChecksNotComplete: Some checks haven’t been completed yet + allChecksSucceeded: All checks have succeeded + allReqChecksPassed: All required checks passed + someChecksFailed: Some checks have failed + someChecksRunning: Some checks are running importFailed: Import Failed uploadAFileError: There is no image or video uploaded. Please upload an image or video. securitySettings: @@ -1018,3 +1076,4 @@ securitySettings: detectDesc: passive vulnerability will report errors but not block block: Block blockDesc: active vulnerability blocks commit if any vulnerability is found +showMoreText: Show More diff --git a/web/src/icons/code-fail.svg b/web/src/icons/code-fail.svg new file mode 100644 index 000000000..e24558d55 --- /dev/null +++ b/web/src/icons/code-fail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/icons/code-success.svg b/web/src/icons/code-success.svg new file mode 100644 index 000000000..8fb95d549 --- /dev/null +++ b/web/src/icons/code-success.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/icons/code-timeout.svg b/web/src/icons/code-timeout.svg new file mode 100644 index 000000000..1ccba495b --- /dev/null +++ b/web/src/icons/code-timeout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/icons/emptyStatus.svg b/web/src/icons/emptyStatus.svg new file mode 100644 index 000000000..ed77dae0e --- /dev/null +++ b/web/src/icons/emptyStatus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/icons/greyCircle.svg b/web/src/icons/greyCircle.svg new file mode 100644 index 000000000..db9552105 --- /dev/null +++ b/web/src/icons/greyCircle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/pages/PullRequest/Checks/Checks.tsx b/web/src/pages/PullRequest/Checks/Checks.tsx index 7aaa5112a..2b0f73804 100644 --- a/web/src/pages/PullRequest/Checks/Checks.tsx +++ b/web/src/pages/PullRequest/Checks/Checks.tsx @@ -123,7 +123,7 @@ export const Checks: React.FC = ({ repoMetadata, pullReqMetadata, p // Set up the polling with setInterval const intervalId = setInterval(fetchAndProcessData, pollingInterval) // Clean up the interval on component unmount - return () => clearInterval(intervalId) + return () => clearInterval(intervalId) // eslint-disable-next-line react-hooks/exhaustive-deps }, [hookData, enqueue, dispatch]) if (!prChecksDecisionResult) { diff --git a/web/src/pages/PullRequest/CodeOwners/CodeOwnersOverview.tsx b/web/src/pages/PullRequest/CodeOwners/CodeOwnersOverview.tsx index 41a01dc67..e5afbc9ee 100644 --- a/web/src/pages/PullRequest/CodeOwners/CodeOwnersOverview.tsx +++ b/web/src/pages/PullRequest/CodeOwners/CodeOwnersOverview.tsx @@ -38,7 +38,7 @@ import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/Exec import { useShowRequestError } from 'hooks/useShowRequestError' import type { TypesCodeOwnerEvaluation, TypesCodeOwnerEvaluationEntry } from 'services/code' import type { PRChecksDecisionResult } from 'hooks/usePRChecksDecision' -import { findChangeReqDecisions, findWaitingDecisions } from 'utils/Utils' +import { CodeOwnerReqDecision, findChangeReqDecisions, findWaitingDecisions } from 'utils/Utils' import css from './CodeOwnersOverview.module.scss' interface ChecksOverviewProps extends Pick { @@ -47,12 +47,6 @@ interface ChecksOverviewProps extends Pick = ({ repoMetadata, pul ) } -const CodeOwnerSection: React.FC = ({ data }) => { +export const CodeOwnerSection: React.FC = ({ data }) => { const { getString } = useStrings() const columns = useMemo( () => [ { id: 'CODE', - width: '50%', + width: '47%', sort: true, Header: 'CODE', accessor: 'CODE', @@ -233,7 +227,7 @@ const CodeOwnerSection: React.FC = ({ data }) => { { id: 'approvals', Header: 'APPROVALS', - width: '15%', + width: '18%', sort: true, accessor: 'APPROVALS', Cell: ({ row }: CellProps) => { @@ -247,8 +241,8 @@ const CodeOwnerSection: React.FC = ({ data }) => { return ( {getString('requestChanges')} @@ -259,7 +253,7 @@ const CodeOwnerSection: React.FC = ({ data }) => { {getString('approved')} @@ -332,10 +326,6 @@ const CodeOwnerSection: React.FC = ({ data }) => { - - {getString('codeOwner.title')} - - { @@ -81,7 +85,7 @@ export const Conversation: React.FC = ({ const { currentUser, routes } = useAppContext() const location = useLocation() const activities = usePullReqActivities() - const { data: reviewers, refetch: refetchReviewers } = useGet({ + const { data: reviewers, refetch: refetchReviewers } = useGet({ path: `/api/v1/repos/${repoMetadata.path}/+/pullreq/${pullReqMetadata.number}/reviewers`, debounce: 500 }) @@ -370,17 +374,17 @@ export const Conversation: React.FC = ({ - + /> */} - {prChecksDecisionResult && ( + {/* {prChecksDecisionResult && ( = ({ pullReqMetadata={pullReqMetadata} prChecksDecisionResult={prChecksDecisionResult} /> - )} + )} */} + {prChecksDecisionResult && codeOwners && ( + + + + )} {(hasDescription || showEditDescription) && ( ) => void + mergeOption: PRMergeOption + allowedStrats: string[] + mergeOptions: PRMergeOption[] + setMergeOption: (val: PRMergeOption) => void + mergeable: boolean + ruleViolation: boolean + bypass: boolean + mergePR: ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: any, + mutateRequestOptions?: + | MutateRequestOptions< + { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any + }, + unknown + > + | undefined // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) => Promise + setPrMerged: React.Dispatch> + pullReqMetadata: TypesPullReq + onPRStateChanged: () => void + setRuleViolationArr: React.Dispatch< + React.SetStateAction< + | { + data: { + rule_violations: TypesRuleViolations[] + } + } + | undefined + > + > +} + +const MergeSideDialogBox = (props: MergeSideDialogBoxProps) => { + const { + bypass, + ruleViolation, + mergeable, + sideDialogOpen, + setSideDialogOpen, + mergeOption, + allowedStrats, + mergeOptions, + setMergeOption, + mergePR, + setPrMerged, + pullReqMetadata, + onPRStateChanged, + setRuleViolationArr + } = props + const { getString } = useStrings() + const { showError } = useToaster() + const { pullReqCommits } = useGetPullRequestInfo() + const [mergeStrat, setMergeStrat] = useState(mergeOption.value) + + const initialValues = useMemo(() => { + let messageString = '' + if (pullReqCommits?.commits) { + pullReqCommits?.commits.map(commit => { + messageString = `* ${commit.title}\n ${commit.message}\n` + }) + } + return { + commitMessage: messageString + } + }, [pullReqCommits]) + return ( + { + setSideDialogOpen(false) + }}> + { + const payload: OpenapiMergePullReq = { + method: mergeStrat as EnumMergeMethod, + source_sha: pullReqMetadata?.source_sha, + bypass_rules: bypass, + dry_run: false, + message: data.commitMessage + } + mergePR(payload) + .then(() => { + setPrMerged(true) + onPRStateChanged() + setRuleViolationArr(undefined) + }) + .catch(exception => showError(getErrorMessage(exception))) + }}> + {() => ( + + + + + + {getString('pr.mergePR')} + +