mirror of
https://github.com/MichaelMure/git-bug.git
synced 2024-12-15 10:12:06 +03:00
Partial commit for #158
- 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
This commit is contained in:
parent
d673eb97fe
commit
a5e0deeec1
101
webui/src/pages/bug/CommentInput.tsx
Normal file
101
webui/src/pages/bug/CommentInput.tsx
Normal file
@ -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;
|
@ -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 Paper from '@material-ui/core/Paper';
|
||||||
import TextField from '@material-ui/core/TextField/TextField';
|
import TextField from '@material-ui/core/TextField/TextField';
|
||||||
import { fade, makeStyles, Theme } from '@material-ui/core/styles';
|
import { fade, makeStyles, Theme } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import CommentInput from '../bug/CommentInput';
|
||||||
|
|
||||||
import { useNewBugMutation } from './NewBug.generated';
|
import { useNewBugMutation } from './NewBug.generated';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Css in JS styles
|
||||||
*/
|
*/
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
main: {
|
main: {
|
||||||
@ -33,8 +36,10 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'column',
|
||||||
flexWrap: 'wrap',
|
},
|
||||||
|
actions: {
|
||||||
|
display: 'flex',
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@ -43,21 +48,31 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||||||
* Form to create a new issue
|
* Form to create a new issue
|
||||||
*/
|
*/
|
||||||
function NewBugPage() {
|
function NewBugPage() {
|
||||||
const classes = useStyles();
|
|
||||||
let inputField: any;
|
|
||||||
const [newBug, { loading, error }] = useNewBugMutation();
|
const [newBug, { loading, error }] = useNewBugMutation();
|
||||||
|
const [issueTitle, setIssueTitle] = useState('');
|
||||||
|
const [issueComment, setIssueComment] = useState('');
|
||||||
|
const classes = useStyles();
|
||||||
|
let issueTitleInput: any;
|
||||||
|
|
||||||
function submitNewIssue(e: FormEvent) {
|
function submitNewIssue(e: FormEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (!isFormValid()) return;
|
||||||
|
console.log('submitNewISsue');
|
||||||
|
console.log('title: ', issueTitle);
|
||||||
|
console.log('comment: ', issueComment);
|
||||||
newBug({
|
newBug({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
title: String(inputField.value),
|
title: issueTitle,
|
||||||
message: 'Message', //TODO
|
message: issueComment,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
inputField.value = '';
|
issueTitleInput.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFormValid() {
|
||||||
|
return issueTitle.length > 0 && issueComment.length > 0 ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading) return <div>Loading</div>;
|
if (loading) return <div>Loading</div>;
|
||||||
@ -68,15 +83,29 @@ function NewBugPage() {
|
|||||||
<form className={classes.form} onSubmit={submitNewIssue}>
|
<form className={classes.form} onSubmit={submitNewIssue}>
|
||||||
<TextField
|
<TextField
|
||||||
inputRef={(node) => {
|
inputRef={(node) => {
|
||||||
inputField = node;
|
issueTitleInput = node;
|
||||||
}}
|
}}
|
||||||
label="Title"
|
label="Title"
|
||||||
className={classes.titleInput}
|
className={classes.titleInput}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
|
onChange={(event: any) => setIssueTitle(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<button type="submit">Submit</button>
|
<CommentInput
|
||||||
|
loading={false}
|
||||||
|
onChange={(comment: string) => setIssueComment(comment)}
|
||||||
|
/>
|
||||||
|
<div className={classes.actions}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
disabled={isFormValid() ? false : true}
|
||||||
|
>
|
||||||
|
Submit new issue
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user