From 3afec4c78b929734b4aa28a7304f154a21223fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ctan-nhu=E2=80=9D?= <“tan@harness.io”> Date: Wed, 24 May 2023 17:54:28 -0700 Subject: [PATCH] feat: [CODE-350]: Add some PR Comment improvements --- .../components/Changes/Changes.module.scss | 7 +- .../Changes/Changes.module.scss.d.ts | 3 +- web/src/components/Changes/Changes.tsx | 21 ++- .../ReviewSplitButton/ReviewSplitButton.tsx | 11 +- .../CodeCommentSecondarySaveButton.tsx | 74 ++++++++++ .../CodeCommentStatusButton.tsx | 23 ++- .../CodeCommentStatusSelect.tsx | 13 +- .../CommentBox/CommentBox.module.scss | 12 ++ .../CommentBox/CommentBox.module.scss.d.ts | 1 + web/src/components/CommentBox/CommentBox.tsx | 21 ++- .../components/CommitsView/CommitsView.tsx | 42 +++++- web/src/components/DiffViewer/DiffViewer.tsx | 100 ++++++++----- .../components/DiffViewer/DiffViewerUtils.tsx | 1 + .../MarkdownEditorWithPreview.tsx | 10 +- web/src/framework/strings/stringTypes.ts | 9 +- web/src/hooks/useEmitCodeCommentStatus.ts | 12 +- web/src/hooks/useUserPreference.ts | 3 +- web/src/i18n/strings.en.yaml | 9 +- .../Conversation/CodeCommentHeader.tsx | 2 +- .../PullRequest/Conversation/Conversation.tsx | 139 ++++++++---------- .../PullRequestActionsBox.module.scss | 19 ++- .../PullRequestActionsBox.module.scss.d.ts | 4 +- .../PullRequestActionsBox.tsx | 79 +++++----- web/src/pages/PullRequest/PullRequest.tsx | 14 +- .../FileContent/FileContent.tsx | 2 +- .../GeneralSettingsContent.tsx | 1 + 26 files changed, 436 insertions(+), 196 deletions(-) create mode 100644 web/src/components/CodeCommentSecondarySaveButton/CodeCommentSecondarySaveButton.tsx diff --git a/web/src/components/Changes/Changes.module.scss b/web/src/components/Changes/Changes.module.scss index a25b3791b..757d0172b 100644 --- a/web/src/components/Changes/Changes.module.scss +++ b/web/src/components/Changes/Changes.module.scss @@ -103,8 +103,13 @@ } } -.btn { +.reviewButton { &.hide { visibility: hidden; } + + &.disabled { + pointer-events: none; + opacity: 0.5; + } } diff --git a/web/src/components/Changes/Changes.module.scss.d.ts b/web/src/components/Changes/Changes.module.scss.d.ts index 3b9603602..439953952 100644 --- a/web/src/components/Changes/Changes.module.scss.d.ts +++ b/web/src/components/Changes/Changes.module.scss.d.ts @@ -15,7 +15,8 @@ declare const styles: { readonly menuItem: string readonly menuReviewItem: string readonly reviewIcon: string - readonly btn: string + readonly reviewButton: string readonly hide: string + readonly disabled: string } export default styles diff --git a/web/src/components/Changes/Changes.tsx b/web/src/components/Changes/Changes.tsx index dc54c3f91..cef6ed283 100644 --- a/web/src/components/Changes/Changes.tsx +++ b/web/src/components/Changes/Changes.tsx @@ -26,6 +26,7 @@ import { DIFF2HTML_CONFIG, ViewStyle } from 'components/DiffViewer/DiffViewerUti import { NoResultCard } from 'components/NoResultCard/NoResultCard' import type { TypesPullReq, TypesPullReqActivity } from 'services/code' import { useShowRequestError } from 'hooks/useShowRequestError' +import { useAppContext } from 'AppContext' import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner' import { ChangesDropdown } from './ChangesDropdown' import { DiffViewConfiguration } from './DiffViewConfiguration' @@ -88,9 +89,10 @@ export const Changes: React.FC = ({ lazy: !pullRequestMetadata?.number }) const [activities, setActivities] = useState() - const showSpinner = useMemo(() => { - return loading || (loadingActivities && !activities) - }, [loading, loadingActivities, activities]) + const showSpinner = useMemo( + () => loading || (loadingActivities && !activities), + [loading, loadingActivities, activities] + ) const diffStats = useMemo( () => (diffs || []).reduce( @@ -103,6 +105,16 @@ export const Changes: React.FC = ({ ), [diffs] ) + const shouldHideReviewButton = useMemo( + () => readOnly || pullRequestMetadata?.state === 'merged' || pullRequestMetadata?.state === 'closed', + [readOnly, pullRequestMetadata?.state] + ) + const { currentUser } = useAppContext() + const isActiveUserPROwner = useMemo(() => { + return ( + !!currentUser?.uid && !!pullRequestMetadata?.author?.uid && currentUser?.uid === pullRequestMetadata?.author?.uid + ) + }, [currentUser, pullRequestMetadata]) // Optimization to avoid showing unnecessary loading spinner. The trick is to // show only the spinner when the component is mounted and not when refetching @@ -208,10 +220,11 @@ export const Changes: React.FC = ({ diff --git a/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx b/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx index 87fcaef74..6ca75399b 100644 --- a/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx +++ b/web/src/components/Changes/ReviewSplitButton/ReviewSplitButton.tsx @@ -32,9 +32,10 @@ interface ReviewSplitButtonProps extends Pick { shouldHide: boolean pullRequestMetadata?: TypesPullReq refreshPr: () => void + disabled?: boolean } const ReviewSplitButton = (props: ReviewSplitButtonProps) => { - const { pullRequestMetadata, repoMetadata, shouldHide, refreshPr } = props + const { pullRequestMetadata, repoMetadata, shouldHide, refreshPr, disabled } = props const { getString } = useStrings() const { showError, showSuccess } = useToaster() @@ -75,7 +76,11 @@ const ReviewSplitButton = (props: ReviewSplitButtonProps) => { .catch(exception => showError(getErrorMessage(exception))) }, [decisionOption, mutate, showError, showSuccess, getString, refreshPr, pullRequestMetadata?.source_sha]) return ( - + { , + ButtonProps { + commentItems: CommentItem[] +} + +export const CodeCommentSecondarySaveButton: React.FC = ({ + repoMetadata, + pullRequestMetadata, + commentItems, + onClick, + ...props +}) => { + const { getString } = useStrings() + const isMounted = useIsMounted() + const { showError } = useToaster() + const path = useMemo( + () => `/api/v1/repos/${repoMetadata.path}/+/pullreq/${pullRequestMetadata?.number}/comments`, + [repoMetadata.path, pullRequestMetadata?.number] + ) + const { mutate: updateCodeCommentStatus } = useMutate({ verb: 'PUT', path: ({ id }) => `${path}/${id}/status` }) + const [resolved, setResolved] = useState(commentItems[0]?.payload?.resolved ? true : false) + const emitCodeCommentStatus = useEmitCodeCommentStatus({ + id: commentItems[0]?.payload?.id, + onMatch: status => { + if (isMounted.current) { + setResolved(status === CodeCommentState.RESOLVED) + } + } + }) + + return ( +