mirror of
https://github.com/MichaelMure/git-bug.git
synced 2025-01-06 09:58:32 +03:00
commit
b6a967efac
197
webui/src/components/BugTitleForm/BugTitleForm.tsx
Normal file
197
webui/src/components/BugTitleForm/BugTitleForm.tsx
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
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),
|
||||||
|
},
|
||||||
|
greenButton: {
|
||||||
|
marginLeft: '8px',
|
||||||
|
backgroundColor: '#2ea44fd9',
|
||||||
|
color: '#fff',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: '#2ea44f',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 [bugTitleEdition, setbugTitleEdition] = 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(() => setbugTitleEdition(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelChange() {
|
||||||
|
setIssueTitle(bug.title);
|
||||||
|
setbugTitleEdition(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={() => setbugTitleEdition(!bugTitleEdition)}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={classes.greenButton}
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
href="/new"
|
||||||
|
>
|
||||||
|
New issue
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading) return <div>Loading...</div>;
|
||||||
|
if (error) return <div>Error</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.header}>
|
||||||
|
{bugTitleEdition ? 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;
|
7
webui/src/components/BugTitleForm/SetTitle.graphql
Normal file
7
webui/src/components/BugTitleForm/SetTitle.graphql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
mutation setTitle($input: SetTitleInput!) {
|
||||||
|
setTitle(input: $input) {
|
||||||
|
bug {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Typography from '@material-ui/core/Typography/Typography';
|
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
import Author from 'src/components/Author';
|
import BugTitleForm from 'src/components/BugTitleForm/BugTitleForm';
|
||||||
import Date from 'src/components/Date';
|
|
||||||
import Label from 'src/components/Label';
|
import Label from 'src/components/Label';
|
||||||
import IfLoggedIn from 'src/layout/IfLoggedIn';
|
import IfLoggedIn from 'src/layout/IfLoggedIn';
|
||||||
|
|
||||||
@ -12,21 +10,19 @@ import { BugFragment } from './Bug.generated';
|
|||||||
import CommentForm from './CommentForm';
|
import CommentForm from './CommentForm';
|
||||||
import TimelineQuery from './TimelineQuery';
|
import TimelineQuery from './TimelineQuery';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Css in JS Styles
|
||||||
|
*/
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
main: {
|
main: {
|
||||||
maxWidth: 1000,
|
maxWidth: 1000,
|
||||||
margin: 'auto',
|
margin: 'auto',
|
||||||
marginTop: theme.spacing(4),
|
marginTop: theme.spacing(4),
|
||||||
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
marginLeft: theme.spacing(3) + 40,
|
marginLeft: theme.spacing(3) + 40,
|
||||||
},
|
marginRight: theme.spacing(2),
|
||||||
title: {
|
|
||||||
...theme.typography.h5,
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
...theme.typography.subtitle1,
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -73,17 +69,11 @@ type Props = {
|
|||||||
|
|
||||||
function Bug({ bug }: Props) {
|
function Bug({ bug }: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className={classes.main}>
|
<main className={classes.main}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<span className={classes.title}>{bug.title}</span>
|
<BugTitleForm bug={bug} />
|
||||||
<span className={classes.id}>{bug.humanId}</span>
|
|
||||||
|
|
||||||
<Typography color={'textSecondary'}>
|
|
||||||
<Author author={bug.author} />
|
|
||||||
{' opened this bug '}
|
|
||||||
<Date date={bug.createdAt} />
|
|
||||||
</Typography>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
|
@ -64,9 +64,6 @@ function NewBugPage() {
|
|||||||
function submitNewIssue(e: FormEvent) {
|
function submitNewIssue(e: FormEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!isFormValid()) return;
|
if (!isFormValid()) return;
|
||||||
console.log('submitNewISsue');
|
|
||||||
console.log('title: ', issueTitle);
|
|
||||||
console.log('comment: ', issueComment);
|
|
||||||
newBug({
|
newBug({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
@ -82,7 +79,7 @@ function NewBugPage() {
|
|||||||
return issueTitle.length > 0 && issueComment.length > 0 ? true : false;
|
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>;
|
if (error) return <div>Error</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
Loading…
Reference in New Issue
Block a user