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 paddingLeft: theme.spacing(1),
61 paddingRight: theme.spacing(1),
62 },
63 headerActions: {
64 color: theme.palette.info.contrastText,
65 padding: '0rem',
66 marginLeft: theme.spacing(1),
67 fontSize: '0.75rem',
68 '&:hover': {
69 backgroundColor: 'inherit',
70 },
71 },
72}));
73
74type HistBtnProps = {
75 bugId: string;
76 commentId: string;
77};
78function HistoryMenuToggleButton({ bugId, commentId }: HistBtnProps) {
79 const classes = useStyles();
80 const [open, setOpen] = React.useState(false);
81
82 const handleClickOpen = () => {
83 setOpen(true);
84 };
85
86 const handleClose = () => {
87 setOpen(false);
88 };
89
90 return (
91 <div>
92 <IconButton
93 aria-label="more"
94 aria-controls="long-menu"
95 aria-haspopup="true"
96 onClick={handleClickOpen}
97 className={classes.headerActions}
98 >
99 <HistoryIcon />
100 </IconButton>
101 {
102 // Render CustomizedDialogs on open to prevent fetching the history
103 // before opening the history menu.
104 open && (
105 <MessageHistoryDialog
106 bugId={bugId}
107 commentId={commentId}
108 open={open}
109 onClose={handleClose}
110 />
111 )
112 }
113 </div>
114 );
115}
116
117type Props = {
118 bug: BugFragment;
119 op: AddCommentFragment | CreateFragment;
120};
121function Message({ bug, op }: Props) {
122 const classes = useStyles();
123 const [editMode, switchToEditMode] = useState(false);
124 const [comment, setComment] = useState(op);
125
126 const editComment = (id: String) => {
127 switchToEditMode(true);
128 };
129
130 function readMessageView() {
131 return (
132 <Paper elevation={1} className={classes.bubble}>
133 <header className={classes.header}>
134 <div className={classes.title}>
135 <Author className={classes.author} author={comment.author} />
136 <span> commented </span>
137 <Date date={comment.createdAt} />
138 </div>
139 {comment.edited && (
140 <HistoryMenuToggleButton bugId={bug.id} commentId={comment.id} />
141 )}
142 <IfLoggedIn>
143 {() => (
144 <Tooltip title="Edit Message" placement="top" arrow={true}>
145 <IconButton
146 disableRipple
147 className={classes.headerActions}
148 aria-label="edit message"
149 onClick={() => editComment(comment.id)}
150 >
151 <EditIcon />
152 </IconButton>
153 </Tooltip>
154 )}
155 </IfLoggedIn>
156 </header>
157 <section className={classes.body}>
158 <Content markdown={comment.message} />
159 </section>
160 </Paper>
161 );
162 }
163
164 function editMessageView() {
165 const cancelEdition = () => {
166 switchToEditMode(false);
167 };
168
169 const onPostSubmit = (comment: AddCommentFragment | CreateFragment) => {
170 setComment(comment);
171 switchToEditMode(false);
172 };
173
174 return (
175 <div className={classes.bubble}>
176 <EditCommentForm
177 bug={bug}
178 onCancel={cancelEdition}
179 onPostSubmit={onPostSubmit}
180 comment={comment}
181 />
182 </div>
183 );
184 }
185
186 return (
187 <article className={classes.container}>
188 <Avatar author={comment.author} className={classes.avatar} />
189 {editMode ? editMessageView() : readMessageView()}
190 </article>
191 );
192}
193
194export default Message;