WebUI: Add comment-and-close of a bug in one step

Sascha created

When a user has some text entered in the comment field, the close bug
button will change to "Close bug with comment". This way the user does
not have to comment and close a bug in two separate steps.

Change summary

webui/src/components/CloseBugButton/CloseBugButton.tsx                       |  2 
webui/src/components/CloseBugWithCommentButton/CloseBugWithComment.graphql   | 11 
webui/src/components/CloseBugWithCommentButton/CloseBugWithCommentButton.tsx | 69 
webui/src/pages/bug/CommentForm.tsx                                          | 17 
4 files changed, 91 insertions(+), 8 deletions(-)

Detailed changes

webui/src/components/CloseBugWithCommentButton/CloseBugWithCommentButton.tsx 🔗

@@ -0,0 +1,69 @@
+import React from 'react';
+
+import Button from '@material-ui/core/Button';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
+
+import { BugFragment } from 'src/pages/bug/Bug.generated';
+import { TimelineDocument } from 'src/pages/bug/TimelineQuery.generated';
+
+import { useAddCommentAndCloseBugMutation } from './CloseBugWithComment.generated';
+
+const useStyles = makeStyles((theme: Theme) => ({
+  closeIssueIcon: {
+    color: theme.palette.secondary.dark,
+    paddingTop: '0.1rem',
+  },
+}));
+
+interface Props {
+  bug: BugFragment;
+  comment: string;
+}
+
+function CloseBugWithCommentButton({ bug, comment }: Props) {
+  const [
+    addCommentAndCloseBug,
+    { loading, error },
+  ] = useAddCommentAndCloseBugMutation();
+  const classes = useStyles();
+
+  function addCommentAndCloseBugAction() {
+    addCommentAndCloseBug({
+      variables: {
+        input: {
+          prefix: bug.id,
+          message: comment,
+        },
+      },
+      refetchQueries: [
+        // TODO: update the cache instead of refetching
+        {
+          query: TimelineDocument,
+          variables: {
+            id: bug.id,
+            first: 100,
+          },
+        },
+      ],
+      awaitRefetchQueries: true,
+    });
+  }
+
+  if (loading) return <div>Loading...</div>;
+  if (error) return <div>Error</div>;
+
+  return (
+    <div>
+      <Button
+        variant="contained"
+        onClick={() => addCommentAndCloseBugAction()}
+        startIcon={<ErrorOutlineIcon className={classes.closeIssueIcon} />}
+      >
+        Close bug with comment
+      </Button>
+    </div>
+  );
+}
+
+export default CloseBugWithCommentButton;

webui/src/pages/bug/CommentForm.tsx 🔗

@@ -6,6 +6,7 @@ import { makeStyles, Theme } from '@material-ui/core/styles';
 
 import CommentInput from '../../components/CommentInput/CommentInput';
 import CloseBugButton from 'src/components/CloseBugButton/CloseBugButton';
+import CloseBugWithCommentButton from 'src/components/CloseBugWithCommentButton/CloseBugWithCommentButton';
 import ReopenBugButton from 'src/components/ReopenBugButton/ReopenBugButton';
 
 import { BugFragment } from './Bug.generated';
@@ -77,12 +78,14 @@ function CommentForm({ bug }: Props) {
     if (issueComment.length > 0) submit();
   };
 
-  function getCloseButton() {
-    return <CloseBugButton bug={bug} disabled={issueComment.length > 0} />;
-  }
-
-  function getReopenButton() {
-    return <ReopenBugButton bug={bug} disabled={issueComment.length > 0} />;
+  function getBugStatusButton() {
+    if (bug.status === 'OPEN' && issueComment.length > 0) {
+      return <CloseBugWithCommentButton bug={bug} comment={issueComment} />;
+    } else if (bug.status === 'OPEN') {
+      return <CloseBugButton bug={bug} />;
+    } else {
+      return <ReopenBugButton bug={bug} disabled={issueComment.length > 0} />;
+    }
   }
 
   return (
@@ -94,7 +97,7 @@ function CommentForm({ bug }: Props) {
           onChange={(comment: string) => setIssueComment(comment)}
         />
         <div className={classes.actions}>
-          {bug.status === 'OPEN' ? getCloseButton() : getReopenButton()}
+          {getBugStatusButton()}
           <Button
             className={classes.greenButton}
             variant="contained"