1import React, { useState } from 'react';
2
3import IconButton from '@material-ui/core/IconButton';
4import Paper from '@material-ui/core/Paper';
5import Tooltip from '@material-ui/core/Tooltip/Tooltip';
6import { makeStyles } from '@material-ui/core/styles';
7import EditIcon from '@material-ui/icons/Edit';
8import HistoryIcon from '@material-ui/icons/History';
9
10import Author, { Avatar } from 'src/components/Author';
11import Content from 'src/components/Content';
12import Date from 'src/components/Date';
13import IfLoggedIn from 'src/components/IfLoggedIn/IfLoggedIn';
14
15import { BugFragment } from './Bug.generated';
16import EditCommentForm from './EditCommentForm';
17import { AddCommentFragment } from './MessageCommentFragment.generated';
18import { CreateFragment } from './MessageCreateFragment.generated';
19import MessageHistoryDialog from './MessageHistoryDialog';
20
21const useStyles = makeStyles((theme) => ({
22 author: {
23 fontWeight: 'bold',
24 },
25 container: {
26 display: 'flex',
27 },
28 avatar: {
29 marginTop: 2,
30 },
31 bubble: {
32 flex: 1,
33 marginLeft: theme.spacing(1),
34 minWidth: 0,
35 },
36 header: {
37 ...theme.typography.body1,
38 padding: '0.5rem 1rem',
39 borderBottom: `1px solid ${theme.palette.divider}`,
40 display: 'flex',
41 borderTopRightRadius: theme.shape.borderRadius,
42 borderTopLeftRadius: theme.shape.borderRadius,
43 backgroundColor: theme.palette.info.main,
44 color: theme.palette.info.contrastText,
45 },
46 title: {
47 flex: 1,
48 },
49 tag: {
50 ...theme.typography.button,
51 color: '#888',
52 border: '#ddd solid 1px',
53 padding: '0 0.5rem',
54 fontSize: '0.75rem',
55 borderRadius: 2,
56 marginLeft: '0.5rem',
57 },
58 body: {
59 ...theme.typography.body2,
60 padding: '0.5rem',
61 },
62 headerActions: {
63 color: theme.palette.info.contrastText,
64 padding: '0rem',
65 marginLeft: theme.spacing(1),
66 fontSize: '0.75rem',
67 '&:hover': {
68 backgroundColor: 'inherit',
69 },
70 },
71}));
72
73//TODO Move this button and menu in separate component directory
74//TODO fix failing pipeline due to eslint error
75type HistBtnProps = {
76 bugId: string;
77 commentId: string;
78};
79function HistoryMenuToggleButton({ bugId, commentId }: HistBtnProps) {
80 const classes = useStyles();
81 const [open, setOpen] = React.useState(false);
82
83 const handleClickOpen = () => {
84 setOpen(true);
85 };
86
87 const handleClose = () => {
88 setOpen(false);
89 };
90
91 return (
92 <div>
93 <IconButton
94 aria-label="more"
95 aria-controls="long-menu"
96 aria-haspopup="true"
97 onClick={handleClickOpen}
98 className={classes.headerActions}
99 >
100 <HistoryIcon />
101 </IconButton>
102 {
103 // Render CustomizedDialogs on open to prevent fetching the history
104 // before opening the history menu.
105 open && (
106 <MessageHistoryDialog
107 bugId={bugId}
108 commentId={commentId}
109 open={open}
110 onClose={handleClose}
111 />
112 )
113 }
114 </div>
115 );
116}
117
118type Props = {
119 bug: BugFragment;
120 op: AddCommentFragment | CreateFragment;
121};
122function Message({ bug, op }: Props) {
123 const classes = useStyles();
124 const [editMode, switchToEditMode] = useState(false);
125 const [comment, setComment] = useState(op);
126
127 const editComment = (id: String) => {
128 switchToEditMode(true);
129 };
130
131 function readMessageView() {
132 return (
133 <Paper elevation={1} className={classes.bubble}>
134 <header className={classes.header}>
135 <div className={classes.title}>
136 <Author className={classes.author} author={comment.author} />
137 <span> commented </span>
138 <Date date={comment.createdAt} />
139 </div>
140 {comment.edited && (
141 <HistoryMenuToggleButton bugId={bug.id} commentId={comment.id} />
142 )}
143 <IfLoggedIn>
144 {() => (
145 <Tooltip title="Edit Message" placement="top" arrow={true}>
146 <IconButton
147 disableRipple
148 className={classes.headerActions}
149 aria-label="edit message"
150 onClick={() => editComment(comment.id)}
151 >
152 <EditIcon />
153 </IconButton>
154 </Tooltip>
155 )}
156 </IfLoggedIn>
157 </header>
158 <section className={classes.body}>
159 <Content markdown={comment.message} />
160 </section>
161 </Paper>
162 );
163 }
164
165 function editMessageView() {
166 const cancelEdition = () => {
167 switchToEditMode(false);
168 };
169
170 const onPostSubmit = (comment: AddCommentFragment | CreateFragment) => {
171 setComment(comment);
172 switchToEditMode(false);
173 };
174
175 return (
176 <div className={classes.bubble}>
177 <EditCommentForm
178 bug={bug}
179 onCancel={cancelEdition}
180 onPostSubmit={onPostSubmit}
181 comment={comment}
182 />
183 </div>
184 );
185 }
186
187 return (
188 <article className={classes.container}>
189 <Avatar author={comment.author} className={classes.avatar} />
190 {editMode ? editMessageView() : readMessageView()}
191 </article>
192 );
193}
194
195export default Message;