BugTitleForm.tsx

  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    setTitle({
 82      variables: {
 83        input: {
 84          prefix: bug.humanId,
 85          title: issueTitleInput.value,
 86        },
 87      },
 88      refetchQueries: [
 89        // TODO: update the cache instead of refetching
 90        {
 91          query: TimelineDocument,
 92          variables: {
 93            id: bug.id,
 94            first: 100,
 95          },
 96        },
 97      ],
 98      awaitRefetchQueries: true,
 99    }).then(() => setbugTitleEdition(false));
100  }
101
102  function cancelChange() {
103    setIssueTitle(bug.title);
104    setbugTitleEdition(false);
105  }
106
107  function editableBugTitle() {
108    return (
109      <form className={classes.headerTitle} onSubmit={submitNewTitle}>
110        <BugTitleInput
111          inputRef={(node) => {
112            issueTitleInput = node;
113          }}
114          label="Title"
115          variant="outlined"
116          fullWidth
117          margin="dense"
118          value={issueTitle}
119          onChange={(event: any) => setIssueTitle(event.target.value)}
120        />
121        <div className={classes.editButtonContainer}>
122          <Button
123            className={classes.saveButton}
124            size="small"
125            variant="contained"
126            type="submit"
127            disabled={issueTitle.length === 0}
128          >
129            Save
130          </Button>
131          <Button size="small" onClick={() => cancelChange()}>
132            Cancel
133          </Button>
134        </div>
135      </form>
136    );
137  }
138
139  function readonlyBugTitle() {
140    return (
141      <div className={classes.headerTitle}>
142        <div>
143          <span className={classes.readOnlyTitle}>{bug.title}</span>
144          <span className={classes.readOnlyId}>{bug.humanId}</span>
145        </div>
146        <IfLoggedIn>
147          {() => (
148            <div className={classes.editButtonContainer}>
149              <Button
150                size="small"
151                variant="contained"
152                onClick={() => setbugTitleEdition(!bugTitleEdition)}
153              >
154                Edit
155              </Button>
156              <Button
157                className={classes.greenButton}
158                size="small"
159                variant="contained"
160                href="/new"
161              >
162                New bug
163              </Button>
164            </div>
165          )}
166        </IfLoggedIn>
167      </div>
168    );
169  }
170
171  if (loading) return <div>Loading...</div>;
172  if (error) return <div>Error</div>;
173
174  return (
175    <div className={classes.header}>
176      {bugTitleEdition ? editableBugTitle() : readonlyBugTitle()}
177      <div className="classes.headerSubtitle">
178        <Typography color={'textSecondary'}>
179          <Author author={bug.author} />
180          {' opened this bug '}
181          <Date date={bug.createdAt} />
182        </Typography>
183      </div>
184    </div>
185  );
186}
187
188export default BugTitleForm;