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  titleInput: {
 47    borderRadius: theme.shape.borderRadius,
 48    borderColor: fade(theme.palette.primary.main, 0.2),
 49    borderStyle: 'solid',
 50    borderWidth: '1px',
 51    backgroundColor: fade(theme.palette.primary.main, 0.05),
 52    padding: theme.spacing(0, 0),
 53    minWidth: 336,
 54    transition: theme.transitions.create([
 55      'width',
 56      'borderColor',
 57      'backgroundColor',
 58    ]),
 59  },
 60}));
 61
 62interface Props {
 63  bug: BugFragment;
 64}
 65
 66/**
 67 * Component for bug title change
 68 * @param bug Selected bug in list page
 69 */
 70function BugTitleForm({ bug }: Props) {
 71  const [bugTitleEditable, setBugTitleEditable] = useState(false);
 72  const [setTitle, { loading, error }] = useSetTitleMutation();
 73  const [issueTitle, setIssueTitle] = useState(bug.title);
 74  const classes = useStyles();
 75  let issueTitleInput: any;
 76
 77  function isFormValid() {
 78    if (issueTitleInput) {
 79      return issueTitleInput.value.length > 0 ? true : false;
 80    } else {
 81      return false;
 82    }
 83  }
 84
 85  function submitNewTitle() {
 86    if (!isFormValid()) return;
 87    setTitle({
 88      variables: {
 89        input: {
 90          prefix: bug.humanId,
 91          title: issueTitleInput.value,
 92        },
 93      },
 94      refetchQueries: [
 95        // TODO: update the cache instead of refetching
 96        {
 97          query: TimelineDocument,
 98          variables: {
 99            id: bug.id,
100            first: 100,
101          },
102        },
103      ],
104      awaitRefetchQueries: true,
105    }).then(() => setBugTitleEditable(false));
106  }
107
108  function cancelChange() {
109    setIssueTitle(bug.title);
110    setBugTitleEditable(false);
111  }
112
113  function editableBugTitle() {
114    return (
115      <form className={classes.headerTitle} onSubmit={submitNewTitle}>
116        <TextField
117          inputRef={(node) => {
118            issueTitleInput = node;
119          }}
120          className={classes.titleInput}
121          variant="outlined"
122          fullWidth
123          margin="dense"
124          value={issueTitle}
125          onChange={(event: any) => setIssueTitle(event.target.value)}
126        />
127        <div className={classes.editButtonContainer}>
128          <Button
129            size="small"
130            variant="contained"
131            type="submit"
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        <div className={classes.editButtonContainer}>
152          <Button
153            size="small"
154            variant="contained"
155            onClick={() => setBugTitleEditable(!bugTitleEditable)}
156          >
157            Edit
158          </Button>
159        </div>
160      </div>
161    );
162  }
163
164  if (loading) return <div>Loading...</div>;
165  if (error) return <div>Error</div>;
166
167  return (
168    <div className={classes.header}>
169      {bugTitleEditable ? editableBugTitle() : readonlyBugTitle()}
170      <div className="classes.headerSubtitle">
171        <Typography color={'textSecondary'}>
172          <Author author={bug.author} />
173          {' opened this bug '}
174          <Date date={bug.createdAt} />
175        </Typography>
176      </div>
177    </div>
178  );
179}
180
181export default BugTitleForm;