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 ( +