Partial commit for #158

Cláudio created

- It´s possible to create new issue with title and first message from webui
- form simple validation
- Extraction from CommentForm to create a generic component for Comments

Next steps
- Styles
- Readme update about codegen usage and enforcing playground usage

Change summary

webui/src/pages/bug/CommentInput.tsx | 101 ++++++++++++++++++++++++++++++
webui/src/pages/new/NewBugPage.tsx   |  51 +++++++++++---
2 files changed, 141 insertions(+), 11 deletions(-)

Detailed changes

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

@@ -0,0 +1,101 @@
+import React, { useState, useRef, useEffect } from 'react';
+
+import Button from '@material-ui/core/Button';
+import Paper from '@material-ui/core/Paper';
+import Tab from '@material-ui/core/Tab';
+import Tabs from '@material-ui/core/Tabs';
+import TextField from '@material-ui/core/TextField';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+
+import Content from 'src/components/Content';
+
+import { useAddCommentMutation } from './CommentForm.generated';
+import { TimelineDocument } from './TimelineQuery.generated';
+
+const useStyles = makeStyles((theme) => ({
+  container: {
+    margin: theme.spacing(2, 0),
+    padding: theme.spacing(0, 2, 2, 2),
+  },
+  textarea: {},
+  tabContent: {
+    margin: theme.spacing(2, 0),
+  },
+  preview: {
+    borderBottom: `solid 3px ${theme.palette.grey['200']}`,
+    minHeight: '5rem',
+  },
+  actions: {
+    display: 'flex',
+    justifyContent: 'flex-end',
+  },
+}));
+
+type TabPanelProps = {
+  children: React.ReactNode;
+  value: number;
+  index: number;
+} & React.HTMLProps<HTMLDivElement>;
+function TabPanel({ children, value, index, ...props }: TabPanelProps) {
+  return (
+    <div
+      role="tabpanel"
+      hidden={value !== index}
+      id={`editor-tabpanel-${index}`}
+      aria-labelledby={`editor-tab-${index}`}
+      {...props}
+    >
+      {value === index && children}
+    </div>
+  );
+}
+
+const a11yProps = (index: number) => ({
+  id: `editor-tab-${index}`,
+  'aria-controls': `editor-tabpanel-${index}`,
+});
+
+type Props = {
+  loading: boolean;
+  onChange: (comment: string) => void;
+};
+
+function CommentInput({ loading, onChange }: Props) {
+  const [input, setInput] = useState<string>('');
+  const [tab, setTab] = useState(0);
+  const classes = useStyles();
+
+  useEffect(() => {
+    onChange(input);
+  }, [input]);
+
+  return (
+    <div>
+      <Tabs value={tab} onChange={(_, t) => setTab(t)}>
+        <Tab label="Write" {...a11yProps(0)} />
+        <Tab label="Preview" {...a11yProps(1)} />
+      </Tabs>
+      <div className={classes.tabContent}>
+        <TabPanel value={tab} index={0}>
+          <TextField
+            fullWidth
+            label="Comment"
+            placeholder="Leave a comment"
+            className={classes.textarea}
+            multiline
+            value={input}
+            variant="filled"
+            rows="4" // TODO: rowsMin support
+            onChange={(e: any) => setInput(e.target.value)}
+            disabled={loading}
+          />
+        </TabPanel>
+        <TabPanel value={tab} index={1} className={classes.preview}>
+          <Content markdown={input} />
+        </TabPanel>
+      </div>
+    </div>
+  );
+}
+
+export default CommentInput;

webui/src/pages/new/NewBugPage.tsx 🔗

@@ -1,13 +1,16 @@
-import React, { FormEvent } from 'react';
+import React, { FormEvent, useState } from 'react';
 
+import { Button } from '@material-ui/core';
 import Paper from '@material-ui/core/Paper';
 import TextField from '@material-ui/core/TextField/TextField';
 import { fade, makeStyles, Theme } from '@material-ui/core/styles';
 
+import CommentInput from '../bug/CommentInput';
+
 import { useNewBugMutation } from './NewBug.generated';
 
 /**
- * Styles
+ * Css in JS styles
  */
 const useStyles = makeStyles((theme: Theme) => ({
   main: {
@@ -33,8 +36,10 @@ const useStyles = makeStyles((theme: Theme) => ({
   },
   form: {
     display: 'flex',
-    flexDirection: 'row',
-    flexWrap: 'wrap',
+    flexDirection: 'column',
+  },
+  actions: {
+    display: 'flex',
     justifyContent: 'flex-end',
   },
 }));
@@ -43,21 +48,31 @@ const useStyles = makeStyles((theme: Theme) => ({
  * Form to create a new issue
  */
 function NewBugPage() {
-  const classes = useStyles();
-  let inputField: any;
   const [newBug, { loading, error }] = useNewBugMutation();
+  const [issueTitle, setIssueTitle] = useState('');
+  const [issueComment, setIssueComment] = useState('');
+  const classes = useStyles();
+  let issueTitleInput: any;
 
   function submitNewIssue(e: FormEvent) {
     e.preventDefault();
+    if (!isFormValid()) return;
+    console.log('submitNewISsue');
+    console.log('title: ', issueTitle);
+    console.log('comment: ', issueComment);
     newBug({
       variables: {
         input: {
-          title: String(inputField.value),
-          message: 'Message', //TODO
+          title: issueTitle,
+          message: issueComment,
         },
       },
     });
-    inputField.value = '';
+    issueTitleInput.value = '';
+  }
+
+  function isFormValid() {
+    return issueTitle.length > 0 && issueComment.length > 0 ? true : false;
   }
 
   if (loading) return <div>Loading</div>;
@@ -68,15 +83,29 @@ function NewBugPage() {
       <form className={classes.form} onSubmit={submitNewIssue}>
         <TextField
           inputRef={(node) => {
-            inputField = node;
+            issueTitleInput = node;
           }}
           label="Title"
           className={classes.titleInput}
           variant="outlined"
           fullWidth
           margin="dense"
+          onChange={(event: any) => setIssueTitle(event.target.value)}
+        />
+        <CommentInput
+          loading={false}
+          onChange={(comment: string) => setIssueComment(comment)}
         />
-        <button type="submit">Submit</button>
+        <div className={classes.actions}>
+          <Button
+            variant="contained"
+            color="primary"
+            type="submit"
+            disabled={isFormValid() ? false : true}
+          >
+            Submit new issue
+          </Button>
+        </div>
       </form>
     </Paper>
   );