-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: review pull request modal window (DAP-4764) (#28)
- Loading branch information
Showing
14 changed files
with
1,316 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
libs/engine/src/app/contexts/mutable-web-context/use-mutation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { MutableWebContext } from './mutable-web-context' | ||
import { MutationId } from '../../services/mutation/mutation.entity' | ||
import { useContext, useMemo } from 'react' | ||
|
||
export const useMutation = (mutationId: MutationId) => { | ||
const { mutations } = useContext(MutableWebContext) | ||
|
||
const mutation = useMemo( | ||
() => mutations.find((mutation) => mutation.id === mutationId) ?? null, | ||
[mutations, mutationId] | ||
) | ||
|
||
return { mutation } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
libs/shared-components/src/notifications/pr-reviewer-modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { FC, useMemo } from 'react' | ||
import { Button, Modal } from 'antd' | ||
import toJson from 'json-stringify-deterministic' | ||
import { | ||
NotificationDto, | ||
NotificationType, | ||
PullRequestPayload, | ||
useAcceptPullRequest, | ||
useMutation, | ||
useRejectPullRequest, | ||
} from '@mweb/engine' | ||
import { PrReviewer } from './pr-reviewer' | ||
import { IconBranchButton, IconNotificationClose } from './test-data-notification' | ||
|
||
const leaveMergableProps = (mutation: any): any => { | ||
return { | ||
apps: mutation.apps, | ||
targets: mutation.targets, | ||
metadata: { | ||
description: mutation.metadata.description, | ||
}, | ||
} | ||
} | ||
|
||
export interface Props { | ||
notification: NotificationDto | ||
containerRef: React.RefObject<HTMLElement> | ||
onClose: () => void | ||
} | ||
|
||
export const PrReviewerModal: FC<Props> = ({ notification, containerRef, onClose }) => { | ||
if (notification.type !== NotificationType.PullRequest) { | ||
throw new Error('Only PullRequest notifications are supported') | ||
} | ||
|
||
const { sourceMutationId, targetMutationId } = notification.payload as PullRequestPayload | ||
|
||
const { mutation: source } = useMutation(sourceMutationId) | ||
const { mutation: target } = useMutation(targetMutationId) | ||
|
||
const { acceptPullRequest, isLoading: isLoadingAccept } = useAcceptPullRequest(notification.id) | ||
const { rejectPullRequest, isLoading: isLoadingReject } = useRejectPullRequest(notification.id) | ||
|
||
const sourceJson = useMemo(() => toJson(leaveMergableProps(source), { space: ' ' }), []) | ||
const targetJson = useMemo(() => toJson(leaveMergableProps(target), { space: ' ' }), []) | ||
|
||
const handleAcceptClick = () => { | ||
// ToDo: replace .then() with useEffect? | ||
acceptPullRequest().then(() => onClose()) | ||
} | ||
|
||
const handleDeclineClick = () => { | ||
// ToDo: replace .then() with useEffect? | ||
rejectPullRequest().then(() => onClose()) | ||
} | ||
|
||
return ( | ||
<Modal | ||
title="Review Changes" | ||
open | ||
centered | ||
getContainer={containerRef.current ?? false} | ||
zIndex={10000} | ||
onCancel={onClose} | ||
width={1000} | ||
footer={[ | ||
<Button | ||
key="decline" | ||
loading={isLoadingReject} | ||
disabled={isLoadingAccept || isLoadingReject} | ||
type="default" | ||
size="middle" | ||
onClick={handleDeclineClick} | ||
icon={<IconNotificationClose />} | ||
iconPosition="start" | ||
> | ||
Decline | ||
</Button>, | ||
<Button | ||
key="accept" | ||
loading={isLoadingAccept} | ||
disabled={isLoadingAccept || isLoadingReject} | ||
type="primary" | ||
size="middle" | ||
onClick={handleAcceptClick} | ||
icon={<IconBranchButton />} | ||
iconPosition="start" | ||
> | ||
Accept | ||
</Button>, | ||
]} | ||
> | ||
<PrReviewer modifiedCode={sourceJson} originalCode={targetJson} /> | ||
</Modal> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import React, { useEffect, useRef } from 'react' | ||
import { FC } from 'react' | ||
import CodeMirrorMerge from 'react-codemirror-merge' | ||
import { langs } from '@uiw/codemirror-extensions-langs' | ||
|
||
export interface Props { | ||
originalCode: string | ||
modifiedCode: string | ||
} | ||
|
||
export const PrReviewer: FC<Props> = ({ originalCode, modifiedCode }) => { | ||
const containerRef = useRef<HTMLDivElement>(null) | ||
|
||
// ToDo: workaround that moves styles from head to shadow dom | ||
useEffect(() => { | ||
const observer = new MutationObserver(() => { | ||
const styleElement = document.evaluate( | ||
"//head/style[contains(text(),'cm-')]", | ||
document.head, | ||
null, | ||
XPathResult.FIRST_ORDERED_NODE_TYPE, | ||
null | ||
).singleNodeValue | ||
|
||
if (styleElement) { | ||
setTimeout(() => { | ||
containerRef.current!.append(styleElement) | ||
}, 10) | ||
} | ||
}) | ||
|
||
observer.observe(document.head, { childList: true }) | ||
|
||
return () => { | ||
observer.disconnect() | ||
} | ||
}, []) | ||
|
||
return ( | ||
<div ref={containerRef} style={{ overflowY: 'scroll', maxHeight: 630 }}> | ||
<CodeMirrorMerge> | ||
<CodeMirrorMerge.Original | ||
value={originalCode} | ||
editable={false} | ||
extensions={[langs.json()]} | ||
/> | ||
<CodeMirrorMerge.Modified | ||
value={modifiedCode} | ||
editable={false} | ||
extensions={[langs.json()]} | ||
/> | ||
</CodeMirrorMerge> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.