aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src
diff options
context:
space:
mode:
Diffstat (limited to 'webui/src')
-rw-r--r--webui/src/components/BugTitleForm/BugTitleForm.tsx197
-rw-r--r--webui/src/components/BugTitleForm/SetTitle.graphql7
-rw-r--r--webui/src/pages/bug/Bug.tsx26
-rw-r--r--webui/src/pages/new/NewBugPage.tsx5
4 files changed, 213 insertions, 22 deletions
diff --git a/webui/src/components/BugTitleForm/BugTitleForm.tsx b/webui/src/components/BugTitleForm/BugTitleForm.tsx
new file mode 100644
index 00000000..16441c93
--- /dev/null
+++ b/webui/src/components/BugTitleForm/BugTitleForm.tsx
@@ -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;
diff --git a/webui/src/components/BugTitleForm/SetTitle.graphql b/webui/src/components/BugTitleForm/SetTitle.graphql
new file mode 100644
index 00000000..b96af155
--- /dev/null
+++ b/webui/src/components/BugTitleForm/SetTitle.graphql
@@ -0,0 +1,7 @@
+mutation setTitle($input: SetTitleInput!) {
+ setTitle(input: $input) {
+ bug {
+ id
+ }
+ }
+} \ No newline at end of file
diff --git a/webui/src/pages/bug/Bug.tsx b/webui/src/pages/bug/Bug.tsx
index 8d6d11cc..f2a116f8 100644
--- a/webui/src/pages/bug/Bug.tsx
+++ b/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}>
diff --git a/webui/src/pages/new/NewBugPage.tsx b/webui/src/pages/new/NewBugPage.tsx
index 8e06706f..c70cddaa 100644
--- a/webui/src/pages/new/NewBugPage.tsx
+++ b/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 (