BugTitleForm.tsx

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