Merge pull request #1 from claudioantonio/webui_535

ClΓ‘udio Silva created

Webui 535

Change summary

webui/src/components/BugTitleForm/BugTitleForm.tsx | 181 ++++++++++++++++
webui/src/components/BugTitleForm/SetTitle.graphql |   7 
webui/src/pages/bug/Bug.tsx                        |  26 -
webui/src/pages/new/NewBugPage.tsx                 |   5 
4 files changed, 197 insertions(+), 22 deletions(-)

Detailed changes

webui/src/components/BugTitleForm/BugTitleForm.tsx πŸ”—

@@ -0,0 +1,181 @@
+import React, { useState } from 'react';
+
+import {
+  Button,
+  fade,
+  makeStyles,
+  TextField,
+  Typography,
+} from '@material-ui/core';
+
+import { TimelineDocument } from '../../pages/bug/TimelineQuery.generated';
+import Author from 'src/components/Author';
+import Date from 'src/components/Date';
+import { BugFragment } from 'src/pages/bug/Bug.generated';
+
+import { useSetTitleMutation } from './SetTitle.generated';
+
+/**
+ * Css in JS styles
+ */
+const useStyles = makeStyles((theme) => ({
+  header: {
+    display: 'flex',
+    flexDirection: 'column',
+  },
+  headerTitle: {
+    display: 'flex',
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
+  readOnlyTitle: {
+    ...theme.typography.h5,
+  },
+  readOnlyId: {
+    ...theme.typography.subtitle1,
+    marginLeft: theme.spacing(1),
+  },
+  editButtonContainer: {
+    display: 'flex',
+    flexDirection: 'row',
+    justifyContent: 'flex-start',
+    alignItems: 'center',
+    minWidth: 200,
+    marginLeft: theme.spacing(2),
+  },
+  titleInput: {
+    borderRadius: theme.shape.borderRadius,
+    borderColor: fade(theme.palette.primary.main, 0.2),
+    borderStyle: 'solid',
+    borderWidth: '1px',
+    backgroundColor: fade(theme.palette.primary.main, 0.05),
+    padding: theme.spacing(0, 0),
+    minWidth: 336,
+    transition: theme.transitions.create([
+      'width',
+      'borderColor',
+      'backgroundColor',
+    ]),
+  },
+}));
+
+interface Props {
+  bug: BugFragment;
+}
+
+/**
+ * Component for bug title change
+ * @param bug Selected bug in list page
+ */
+function BugTitleForm({ bug }: Props) {
+  const [bugTitleEditable, setBugTitleEditable] = useState(false);
+  const [setTitle, { loading, error }] = useSetTitleMutation();
+  const [issueTitle, setIssueTitle] = useState(bug.title);
+  const classes = useStyles();
+  let issueTitleInput: any;
+
+  function isFormValid() {
+    if (issueTitleInput) {
+      return issueTitleInput.value.length > 0 ? true : false;
+    } else {
+      return false;
+    }
+  }
+
+  function submitNewTitle() {
+    if (!isFormValid()) return;
+    setTitle({
+      variables: {
+        input: {
+          prefix: bug.humanId,
+          title: issueTitleInput.value,
+        },
+      },
+      refetchQueries: [
+        // TODO: update the cache instead of refetching
+        {
+          query: TimelineDocument,
+          variables: {
+            id: bug.id,
+            first: 100,
+          },
+        },
+      ],
+      awaitRefetchQueries: true,
+    }).then(() => setBugTitleEditable(false));
+  }
+
+  function cancelChange() {
+    setIssueTitle(bug.title);
+    setBugTitleEditable(false);
+  }
+
+  function editableBugTitle() {
+    return (
+      <form className={classes.headerTitle} onSubmit={submitNewTitle}>
+        <TextField
+          inputRef={(node) => {
+            issueTitleInput = node;
+          }}
+          className={classes.titleInput}
+          variant="outlined"
+          fullWidth
+          margin="dense"
+          value={issueTitle}
+          onChange={(event: any) => setIssueTitle(event.target.value)}
+        />
+        <div className={classes.editButtonContainer}>
+          <Button
+            size="small"
+            variant="contained"
+            type="submit"
+            disabled={issueTitle.length === 0}
+          >
+            Save
+          </Button>
+          <Button size="small" onClick={() => cancelChange()}>
+            Cancel
+          </Button>
+        </div>
+      </form>
+    );
+  }
+
+  function readonlyBugTitle() {
+    return (
+      <div className={classes.headerTitle}>
+        <div>
+          <span className={classes.readOnlyTitle}>{bug.title}</span>
+          <span className={classes.readOnlyId}>{bug.humanId}</span>
+        </div>
+        <div className={classes.editButtonContainer}>
+          <Button
+            size="small"
+            variant="contained"
+            onClick={() => setBugTitleEditable(!bugTitleEditable)}
+          >
+            Edit
+          </Button>
+        </div>
+      </div>
+    );
+  }
+
+  if (loading) return <div>Loading...</div>;
+  if (error) return <div>Error</div>;
+
+  return (
+    <div className={classes.header}>
+      {bugTitleEditable ? editableBugTitle() : readonlyBugTitle()}
+      <div className="classes.headerSubtitle">
+        <Typography color={'textSecondary'}>
+          <Author author={bug.author} />
+          {' opened this bug '}
+          <Date date={bug.createdAt} />
+        </Typography>
+      </div>
+    </div>
+  );
+}
+
+export default BugTitleForm;

webui/src/pages/bug/Bug.tsx πŸ”—

@@ -1,10 +1,8 @@
 import React from 'react';
 
-import Typography from '@material-ui/core/Typography/Typography';
 import { makeStyles } from '@material-ui/core/styles';
 
-import Author from 'src/components/Author';
-import Date from 'src/components/Date';
+import BugTitleForm from 'src/components/BugTitleForm/BugTitleForm';
 import Label from 'src/components/Label';
 import IfLoggedIn from 'src/layout/IfLoggedIn';
 
@@ -12,21 +10,19 @@ import { BugFragment } from './Bug.generated';
 import CommentForm from './CommentForm';
 import TimelineQuery from './TimelineQuery';
 
+/**
+ * Css in JS Styles
+ */
 const useStyles = makeStyles((theme) => ({
   main: {
     maxWidth: 1000,
     margin: 'auto',
     marginTop: theme.spacing(4),
+    overflow: 'hidden',
   },
   header: {
     marginLeft: theme.spacing(3) + 40,
-  },
-  title: {
-    ...theme.typography.h5,
-  },
-  id: {
-    ...theme.typography.subtitle1,
-    marginLeft: theme.spacing(1),
+    marginRight: theme.spacing(2),
   },
   container: {
     display: 'flex',
@@ -73,17 +69,11 @@ type Props = {
 
 function Bug({ bug }: Props) {
   const classes = useStyles();
+
   return (
     <main className={classes.main}>
       <div className={classes.header}>
-        <span className={classes.title}>{bug.title}</span>
-        <span className={classes.id}>{bug.humanId}</span>
-
-        <Typography color={'textSecondary'}>
-          <Author author={bug.author} />
-          {' opened this bug '}
-          <Date date={bug.createdAt} />
-        </Typography>
+        <BugTitleForm bug={bug} />
       </div>
 
       <div className={classes.container}>

webui/src/pages/new/NewBugPage.tsx πŸ”—

@@ -64,9 +64,6 @@ function NewBugPage() {
   function submitNewIssue(e: FormEvent) {
     e.preventDefault();
     if (!isFormValid()) return;
-    console.log('submitNewISsue');
-    console.log('title: ', issueTitle);
-    console.log('comment: ', issueComment);
     newBug({
       variables: {
         input: {
@@ -82,7 +79,7 @@ function NewBugPage() {
     return issueTitle.length > 0 && issueComment.length > 0 ? true : false;
   }
 
-  if (loading) return <div>Loading</div>;
+  if (loading) return <div>Loading...</div>;
   if (error) return <div>Error</div>;
 
   return (