1import React, { useState } from 'react';
2import { Link } from 'react-router-dom';
3
4import { Button, makeStyles, Typography } from '@material-ui/core';
5
6import { TimelineDocument } from '../../pages/bug/TimelineQuery.generated';
7import IfLoggedIn from '../IfLoggedIn/IfLoggedIn';
8import Author from 'src/components/Author';
9import Date from 'src/components/Date';
10import { BugFragment } from 'src/pages/bug/Bug.generated';
11
12import BugTitleInput from './BugTitleInput';
13import { useSetTitleMutation } from './SetTitle.generated';
14
15/**
16 * Css in JS styles
17 */
18const useStyles = makeStyles((theme) => ({
19 header: {
20 display: 'flex',
21 flexDirection: 'column',
22 },
23 headerTitle: {
24 display: 'flex',
25 flexDirection: 'row',
26 justifyContent: 'space-between',
27 },
28 readOnlyTitle: {
29 ...theme.typography.h5,
30 },
31 readOnlyId: {
32 ...theme.typography.subtitle1,
33 marginLeft: theme.spacing(1),
34 },
35 editButtonContainer: {
36 display: 'flex',
37 flexDirection: 'row',
38 justifyContent: 'flex-start',
39 alignItems: 'center',
40 minWidth: 200,
41 marginLeft: theme.spacing(2),
42 },
43 greenButton: {
44 marginLeft: theme.spacing(1),
45 backgroundColor: theme.palette.success.main,
46 color: theme.palette.success.contrastText,
47 '&:hover': {
48 backgroundColor: theme.palette.success.dark,
49 color: theme.palette.primary.contrastText,
50 },
51 },
52 saveButton: {
53 marginRight: theme.spacing(1),
54 },
55}));
56
57interface Props {
58 bug: BugFragment;
59}
60
61/**
62 * Component for bug title change
63 * @param bug Selected bug in list page
64 */
65function BugTitleForm({ bug }: Props) {
66 const [bugTitleEdition, setbugTitleEdition] = useState(false);
67 const [setTitle, { loading, error }] = useSetTitleMutation();
68 const [issueTitle, setIssueTitle] = useState(bug.title);
69 const classes = useStyles();
70 let issueTitleInput: any;
71
72 function isFormValid() {
73 if (issueTitleInput) {
74 return issueTitleInput.value.length > 0;
75 } else {
76 return false;
77 }
78 }
79
80 function submitNewTitle() {
81 if (!isFormValid()) return;
82 if (bug.title === issueTitleInput.value) {
83 cancelChange();
84 return;
85 }
86 setTitle({
87 variables: {
88 input: {
89 prefix: bug.humanId,
90 title: issueTitleInput.value,
91 },
92 },
93 refetchQueries: [
94 // TODO: update the cache instead of refetching
95 {
96 query: TimelineDocument,
97 variables: {
98 id: bug.id,
99 first: 100,
100 },
101 },
102 ],
103 awaitRefetchQueries: true,
104 }).then(() => setbugTitleEdition(false));
105 }
106
107 function cancelChange() {
108 setIssueTitle(bug.title);
109 setbugTitleEdition(false);
110 }
111
112 function editableBugTitle() {
113 return (
114 <form className={classes.headerTitle}>
115 <BugTitleInput
116 inputRef={(node) => {
117 issueTitleInput = node;
118 }}
119 label="Title"
120 variant="outlined"
121 fullWidth
122 margin="dense"
123 value={issueTitle}
124 onChange={(event: any) => setIssueTitle(event.target.value)}
125 />
126 <div className={classes.editButtonContainer}>
127 <Button
128 className={classes.saveButton}
129 size="small"
130 variant="contained"
131 onClick={() => submitNewTitle()}
132 disabled={issueTitle.length === 0}
133 >
134 Save
135 </Button>
136 <Button size="small" onClick={() => cancelChange()}>
137 Cancel
138 </Button>
139 </div>
140 </form>
141 );
142 }
143
144 function readonlyBugTitle() {
145 return (
146 <div className={classes.headerTitle}>
147 <div>
148 <span className={classes.readOnlyTitle}>{bug.title}</span>
149 <span className={classes.readOnlyId}>{bug.humanId}</span>
150 </div>
151 <IfLoggedIn>
152 {() => (
153 <div className={classes.editButtonContainer}>
154 <Button
155 size="small"
156 variant="contained"
157 onClick={() => setbugTitleEdition(!bugTitleEdition)}
158 >
159 Edit
160 </Button>
161 <Button
162 className={classes.greenButton}
163 size="small"
164 variant="contained"
165 component={Link}
166 to="/new"
167 >
168 New bug
169 </Button>
170 </div>
171 )}
172 </IfLoggedIn>
173 </div>
174 );
175 }
176
177 if (loading) return <div>Loading...</div>;
178 if (error) return <div>Error</div>;
179
180 return (
181 <div className={classes.header}>
182 {bugTitleEdition ? editableBugTitle() : readonlyBugTitle()}
183 <div className="classes.headerSubtitle">
184 <Typography color={'textSecondary'}>
185 <Author author={bug.author} />
186 {' opened this bug '}
187 <Date date={bug.createdAt} />
188 </Typography>
189 </div>
190 </div>
191 );
192}
193
194export default BugTitleForm;