From 51ad239553a745c6761d8afe8f72ac3ef42ab0e9 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Wed, 16 Nov 2022 11:45:27 +0100 Subject: [PATCH] first draft of the comments ui (#2440) --- .../ChangeRequestComments/AddCommentField.tsx | 44 +++++++++++++++++ .../ChangeRequestComment.tsx | 47 +++++++++++++++++++ .../ChangeRequestComments/StyledAvatar.tsx | 7 +++ .../ChangeRequestOverview.tsx | 42 +++++++++++++++-- .../changeRequest/DraftBanner/DraftBanner.tsx | 2 +- .../changeRequest/changeRequest.types.ts | 8 ++++ .../useChangeRequestApi.ts | 19 ++++++++ 7 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/AddCommentField.tsx create mode 100644 frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/ChangeRequestComment.tsx create mode 100644 frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/StyledAvatar.tsx diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/AddCommentField.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/AddCommentField.tsx new file mode 100644 index 0000000000..5af6441d2c --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/AddCommentField.tsx @@ -0,0 +1,44 @@ +import { FC } from 'react'; +import { Box, Button, styled, TextField } from '@mui/material'; +import { StyledAvatar } from './StyledAvatar'; + +const AddCommentWrapper = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(2), + marginTop: theme.spacing(2), + marginBottom: theme.spacing(1), +})); + +export const AddCommentField: FC<{ + imageUrl: string; + commentText: string; + onAddComment: () => void; + onTypeComment: (text: string) => void; +}> = ({ imageUrl, commentText, onTypeComment, onAddComment }) => ( + <> + + + onTypeComment(e.target.value)} + value={commentText} + /> + + + + + +); diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/ChangeRequestComment.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/ChangeRequestComment.tsx new file mode 100644 index 0000000000..df2e6c800b --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/ChangeRequestComment.tsx @@ -0,0 +1,47 @@ +import { FC } from 'react'; +import Paper from '@mui/material/Paper'; +import { Box, styled, Typography } from '@mui/material'; +import TimeAgo from 'react-timeago'; +import { StyledAvatar } from './StyledAvatar'; +import { IChangeRequestComment } from '../../changeRequest.types'; + +const ChangeRequestCommentWrapper = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(2), + marginTop: theme.spacing(2), +})); +const CommentPaper = styled(Paper)(({ theme }) => ({ + width: '100%', + padding: theme.spacing(2), + backgroundColor: theme.palette.tertiary.light, +})); + +const CommentHeader = styled(Box)(({ theme }) => ({ + display: 'flex', + borderBottom: '1px solid', + borderColor: theme.palette.divider, + paddingBottom: theme.spacing(1), +})); + +export const ChangeRequestComment: FC<{ comment: IChangeRequestComment }> = ({ + comment, +}) => ( + + + + + + {comment.createdBy.username}{' '} + + commented{' '} + + + + + {comment.text} + + +); diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/StyledAvatar.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/StyledAvatar.tsx new file mode 100644 index 0000000000..5aa775b090 --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestComments/StyledAvatar.tsx @@ -0,0 +1,7 @@ +import { Avatar, styled } from '@mui/material'; + +export const StyledAvatar = styled(Avatar)(({ theme }) => ({ + height: '30px', + width: '30px', + marginTop: theme.spacing(1), +})); diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx index bab9d3359d..ba8270e6e0 100644 --- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx @@ -1,5 +1,5 @@ -import { Alert, styled } from '@mui/material'; -import { FC, useContext } from 'react'; +import { Alert, Button, styled, TextField, Typography } from '@mui/material'; +import { FC, useContext, useState } from 'react'; import { Box } from '@mui/material'; import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest'; import { ChangeRequestHeader } from './ChangeRequestHeader/ChangeRequestHeader'; @@ -19,6 +19,14 @@ import PermissionButton from 'component/common/PermissionButton/PermissionButton import { APPLY_CHANGE_REQUEST } from 'component/providers/AccessProvider/permissions'; import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; import AccessContext from 'contexts/AccessContext'; +import { + StyledAvatar, + StyledCard, +} from './ChangeRequestHeader/ChangeRequestHeader.styles'; +import TimeAgo from 'react-timeago'; +import { InputProps as StandardInputProps } from '@mui/material/Input/Input'; +import { ChangeRequestComment } from './ChangeRequestComments/ChangeRequestComment'; +import { AddCommentField } from './ChangeRequestComments/AddCommentField'; const StyledAsideBox = styled(Box)(({ theme }) => ({ width: '30%', @@ -48,13 +56,14 @@ export const ChangeRequestOverview: FC = () => { const projectId = useRequiredPathParam('projectId'); const { user } = useAuthUser(); const { isAdmin } = useContext(AccessContext); + const [commentText, setCommentText] = useState(''); const id = useRequiredPathParam('id'); const { data: changeRequest, refetchChangeRequest } = useChangeRequest( projectId, id ); - const { changeState } = useChangeRequestApi(); + const { changeState, addComment } = useChangeRequestApi(); const { setToastData, setToastApiError } = useToast(); if (!changeRequest) { @@ -77,6 +86,21 @@ export const ChangeRequestOverview: FC = () => { } }; + const onAddComment = async () => { + try { + await addComment(projectId, id, commentText); + setCommentText(''); + refetchChangeRequest(); + setToastData({ + type: 'success', + title: 'Success', + text: 'Comment added', + }); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }; + const isSelfReview = changeRequest?.createdBy.id === user?.id && changeRequest.state === 'In review' && @@ -109,6 +133,18 @@ export const ChangeRequestOverview: FC = () => { Changes + {changeRequest.comments?.map(comment => ( + + ))} + ({ position: 'sticky', top: -1, - zIndex: 200 /* has to lower than header.zIndex */, + zIndex: 250 /* has to lower than header.zIndex and higher than body.zIndex */, borderTop: `1px solid ${theme.palette.warning.border}`, borderBottom: `1px solid ${theme.palette.warning.border}`, backgroundColor: theme.palette.warning.light, diff --git a/frontend/src/component/changeRequest/changeRequest.types.ts b/frontend/src/component/changeRequest/changeRequest.types.ts index 4b79378302..64460c7361 100644 --- a/frontend/src/component/changeRequest/changeRequest.types.ts +++ b/frontend/src/component/changeRequest/changeRequest.types.ts @@ -10,6 +10,7 @@ export interface IChangeRequest { createdAt: Date; features: IChangeRequestFeature[]; approvals: IChangeRequestApproval[]; + comments: IChangeRequestComment[]; conflict?: string; } @@ -30,6 +31,13 @@ export interface IChangeRequestApproval { createdAt: Date; } +export interface IChangeRequestComment { + text: string; + createdBy: Pick; + createdAt: Date; + id: string; +} + export interface IChangeRequestBase { id: number; action: ChangeRequestAction; diff --git a/frontend/src/hooks/api/actions/useChangeRequestApi/useChangeRequestApi.ts b/frontend/src/hooks/api/actions/useChangeRequestApi/useChangeRequestApi.ts index 0830c17b26..38228ac511 100644 --- a/frontend/src/hooks/api/actions/useChangeRequestApi/useChangeRequestApi.ts +++ b/frontend/src/hooks/api/actions/useChangeRequestApi/useChangeRequestApi.ts @@ -98,12 +98,31 @@ export const useChangeRequestApi = () => { } }; + const addComment = async ( + projectId: string, + changeSetId: string, + text: string + ) => { + const path = `/api/admin/projects/${projectId}/change-requests/${changeSetId}/comments`; + const req = createRequest(path, { + method: 'POST', + body: JSON.stringify({ text }), + }); + + try { + return await makeRequest(req.caller, req.id); + } catch (e) { + throw e; + } + }; + return { addChangeRequest, changeState, discardChangeRequestEvent, updateChangeRequestEnvironmentConfig, discardDraft, + addComment, errors, loading, };