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