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  },
 47  saveButton: {
 48    marginRight: theme.spacing(1),
 49  },
 50}));
 51
 52interface Props {
 53  bug: BugFragment;
 54}
 55
 56/**
 57 * Component for bug title change
 58 * @param bug Selected bug in list page
 59 */
 60function BugTitleForm({ bug }: Props) {
 61  const [bugTitleEdition, setbugTitleEdition] = useState(false);
 62  const [setTitle, { loading, error }] = useSetTitleMutation();
 63  const [issueTitle, setIssueTitle] = useState(bug.title);
 64  const classes = useStyles();
 65  let issueTitleInput: any;
 66
 67  function isFormValid() {
 68    if (issueTitleInput) {
 69      return issueTitleInput.value.length > 0;
 70    } else {
 71      return false;
 72    }
 73  }
 74
 75  function submitNewTitle() {
 76    if (!isFormValid()) return;
 77    setTitle({
 78      variables: {
 79        input: {
 80          prefix: bug.humanId,
 81          title: issueTitleInput.value,
 82        },
 83      },
 84      refetchQueries: [
 85        // TODO: update the cache instead of refetching
 86        {
 87          query: TimelineDocument,
 88          variables: {
 89            id: bug.id,
 90            first: 100,
 91          },
 92        },
 93      ],
 94      awaitRefetchQueries: true,
 95    }).then(() => setbugTitleEdition(false));
 96  }
 97
 98  function cancelChange() {
 99    setIssueTitle(bug.title);
100    setbugTitleEdition(false);
101  }
102
103  function editableBugTitle() {
104    return (
105      <form className={classes.headerTitle} onSubmit={submitNewTitle}>
106        <BugTitleInput
107          inputRef={(node) => {
108            issueTitleInput = node;
109          }}
110          label="Title"
111          variant="outlined"
112          fullWidth
113          margin="dense"
114          value={issueTitle}
115          onChange={(event: any) => setIssueTitle(event.target.value)}
116        />
117        <div className={classes.editButtonContainer}>
118          <Button
119            className={classes.saveButton}
120            size="small"
121            variant="contained"
122            type="submit"
123            disabled={issueTitle.length === 0}
124          >
125            Save
126          </Button>
127          <Button size="small" onClick={() => cancelChange()}>
128            Cancel
129          </Button>
130        </div>
131      </form>
132    );
133  }
134
135  function readonlyBugTitle() {
136    return (
137      <div className={classes.headerTitle}>
138        <div>
139          <span className={classes.readOnlyTitle}>{bug.title}</span>
140          <span className={classes.readOnlyId}>{bug.humanId}</span>
141        </div>
142        <IfLoggedIn>
143          {() => (
144            <div className={classes.editButtonContainer}>
145              <Button
146                size="small"
147                variant="contained"
148                onClick={() => setbugTitleEdition(!bugTitleEdition)}
149              >
150                Edit
151              </Button>
152              <Button
153                className={classes.greenButton}
154                size="small"
155                variant="contained"
156                href="/new"
157              >
158                New issue
159              </Button>
160            </div>
161          )}
162        </IfLoggedIn>
163      </div>
164    );
165  }
166
167  if (loading) return <div>Loading...</div>;
168  if (error) return <div>Error</div>;
169
170  return (
171    <div className={classes.header}>
172      {bugTitleEdition ? editableBugTitle() : readonlyBugTitle()}
173      <div className="classes.headerSubtitle">
174        <Typography color={'textSecondary'}>
175          <Author author={bug.author} />
176          {' opened this bug '}
177          <Date date={bug.createdAt} />
178        </Typography>
179      </div>
180    </div>
181  );
182}
183
184export default BugTitleForm;