aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src
diff options
context:
space:
mode:
Diffstat (limited to 'webui/src')
-rw-r--r--webui/src/App.tsx2
-rw-r--r--webui/src/components/BackToListButton.tsx36
-rw-r--r--webui/src/components/BugTitleForm/BugTitleForm.tsx2
-rw-r--r--webui/src/components/Content/PreTag.tsx2
-rw-r--r--webui/src/components/Header/Header.tsx73
-rw-r--r--webui/src/pages/bug/Bug.tsx19
-rw-r--r--webui/src/pages/bug/BugQuery.tsx4
-rw-r--r--webui/src/pages/bug/CommentForm.tsx1
-rw-r--r--webui/src/pages/list/BugRow.graphql3
-rw-r--r--webui/src/pages/list/BugRow.tsx16
-rw-r--r--webui/src/pages/list/FilterToolbar.tsx2
-rw-r--r--webui/src/pages/new/NewBugPage.tsx11
-rw-r--r--webui/src/pages/notfound/NotFoundPage.tsx52
-rw-r--r--webui/src/themes/DefaultDark.ts3
-rw-r--r--webui/src/themes/DefaultLight.ts4
15 files changed, 208 insertions, 22 deletions
diff --git a/webui/src/App.tsx b/webui/src/App.tsx
index b9ade974..4c81913c 100644
--- a/webui/src/App.tsx
+++ b/webui/src/App.tsx
@@ -5,6 +5,7 @@ import Layout from './components/Header';
import BugPage from './pages/bug';
import ListPage from './pages/list';
import NewBugPage from './pages/new/NewBugPage';
+import NotFoundPage from './pages/notfound/NotFoundPage';
export default function App() {
return (
@@ -13,6 +14,7 @@ export default function App() {
<Route path="/" exact component={ListPage} />
<Route path="/new" exact component={NewBugPage} />
<Route path="/bug/:id" exact component={BugPage} />
+ <Route component={NotFoundPage} />
</Switch>
</Layout>
);
diff --git a/webui/src/components/BackToListButton.tsx b/webui/src/components/BackToListButton.tsx
new file mode 100644
index 00000000..7ca53ad0
--- /dev/null
+++ b/webui/src/components/BackToListButton.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+
+import Button from '@material-ui/core/Button';
+import { makeStyles } from '@material-ui/core/styles';
+import ArrowBackIcon from '@material-ui/icons/ArrowBack';
+
+const useStyles = makeStyles((theme) => ({
+ backButton: {
+ position: 'sticky',
+ top: '80px',
+ backgroundColor: theme.palette.primary.dark,
+ color: theme.palette.primary.contrastText,
+ '&:hover': {
+ backgroundColor: theme.palette.primary.main,
+ color: theme.palette.primary.contrastText,
+ },
+ },
+}));
+
+function BackToListButton() {
+ const classes = useStyles();
+
+ return (
+ <Button
+ variant="contained"
+ className={classes.backButton}
+ aria-label="back to issue list"
+ href="/"
+ >
+ <ArrowBackIcon />
+ Back to List
+ </Button>
+ );
+}
+
+export default BackToListButton;
diff --git a/webui/src/components/BugTitleForm/BugTitleForm.tsx b/webui/src/components/BugTitleForm/BugTitleForm.tsx
index cc9f5267..a7d5a820 100644
--- a/webui/src/components/BugTitleForm/BugTitleForm.tsx
+++ b/webui/src/components/BugTitleForm/BugTitleForm.tsx
@@ -70,7 +70,7 @@ function BugTitleForm({ bug }: Props) {
function isFormValid() {
if (issueTitleInput) {
- return issueTitleInput.value.length > 0 ? true : false;
+ return issueTitleInput.value.length > 0;
} else {
return false;
}
diff --git a/webui/src/components/Content/PreTag.tsx b/webui/src/components/Content/PreTag.tsx
index 5256ab12..8e352153 100644
--- a/webui/src/components/Content/PreTag.tsx
+++ b/webui/src/components/Content/PreTag.tsx
@@ -11,7 +11,7 @@ const useStyles = makeStyles({
const PreTag = (props: React.HTMLProps<HTMLPreElement>) => {
const classes = useStyles();
- return <pre className={classes.tag} {...props}></pre>;
+ return <pre className={classes.tag} {...props} />;
};
export default PreTag;
diff --git a/webui/src/components/Header/Header.tsx b/webui/src/components/Header/Header.tsx
index 3bdb252f..3064f6e4 100644
--- a/webui/src/components/Header/Header.tsx
+++ b/webui/src/components/Header/Header.tsx
@@ -1,12 +1,15 @@
import React from 'react';
-import { Link } from 'react-router-dom';
+import { Link, useLocation } from 'react-router-dom';
import AppBar from '@material-ui/core/AppBar';
+import Tab, { TabProps } from '@material-ui/core/Tab';
+import Tabs from '@material-ui/core/Tabs';
import Toolbar from '@material-ui/core/Toolbar';
+import Tooltip from '@material-ui/core/Tooltip/Tooltip';
import { makeStyles } from '@material-ui/core/styles';
-import { LightSwitch } from '../../components/Themer';
import CurrentIdentity from '../CurrentIdentity/CurrentIdentity';
+import { LightSwitch } from '../Themer';
const useStyles = makeStyles((theme) => ({
offset: {
@@ -15,9 +18,13 @@ const useStyles = makeStyles((theme) => ({
filler: {
flexGrow: 1,
},
+ appBar: {
+ backgroundColor: theme.palette.primary.dark,
+ color: theme.palette.primary.contrastText,
+ },
appTitle: {
...theme.typography.h6,
- color: 'white',
+ color: theme.palette.primary.contrastText,
textDecoration: 'none',
display: 'flex',
alignItems: 'center',
@@ -31,18 +38,53 @@ const useStyles = makeStyles((theme) => ({
},
}));
+function a11yProps(index: any) {
+ return {
+ id: `nav-tab-${index}`,
+ 'aria-controls': `nav-tabpanel-${index}`,
+ };
+}
+
+const DisabledTabWithTooltip = (props: TabProps) => {
+ /*The span elements around disabled tabs are needed, as the tooltip
+ * won't be triggered by disabled elements.
+ * See: https://material-ui.com/components/tooltips/#disabled-elements
+ * This must be done in a wrapper component, otherwise the TabS component
+ * cannot pass it styles down to the Tab component. Resulting in (console)
+ * warnings. This wrapper acceps the passed down TabProps and pass it around
+ * the span element to the Tab component.
+ */
+ const msg = `This feature doesn't exist yet. Come help us build it.`;
+ return (
+ <Tooltip title={msg}>
+ <span>
+ <Tab disabled {...props} />
+ </span>
+ </Tooltip>
+ );
+};
+
function Header() {
const classes = useStyles();
+ const location = useLocation();
+ const [selectedTab, setTab] = React.useState(location.pathname);
+
+ const handleTabClick = (
+ event: React.ChangeEvent<{}>,
+ newTabValue: string
+ ) => {
+ setTab(newTabValue);
+ };
return (
<>
- <AppBar position="fixed" color="primary">
+ <AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<Link to="/" className={classes.appTitle}>
- <img src="/logo.svg" className={classes.logo} alt="git-bug" />
+ <img src="/logo.svg" className={classes.logo} alt="git-bug logo" />
git-bug
</Link>
- <div className={classes.filler}></div>
+ <div className={classes.filler} />
<div className={classes.lightSwitch}>
<LightSwitch />
</div>
@@ -50,6 +92,25 @@ function Header() {
</Toolbar>
</AppBar>
<div className={classes.offset} />
+ <Tabs
+ centered
+ value={selectedTab}
+ onChange={handleTabClick}
+ aria-label="nav tabs"
+ >
+ <DisabledTabWithTooltip label="Code" value="/code" {...a11yProps(1)} />
+ <Tab label="Bugs" value="/" component={Link} to="/" {...a11yProps(2)} />
+ <DisabledTabWithTooltip
+ label="Pull Requests"
+ value="/pulls"
+ {...a11yProps(3)}
+ />
+ <DisabledTabWithTooltip
+ label="Settings"
+ value="/settings"
+ {...a11yProps(4)}
+ />
+ </Tabs>
</>
);
}
diff --git a/webui/src/pages/bug/Bug.tsx b/webui/src/pages/bug/Bug.tsx
index 83785a37..25281f96 100644
--- a/webui/src/pages/bug/Bug.tsx
+++ b/webui/src/pages/bug/Bug.tsx
@@ -18,11 +18,17 @@ const useStyles = makeStyles((theme) => ({
maxWidth: 1000,
margin: 'auto',
marginTop: theme.spacing(4),
- overflow: 'hidden',
},
header: {
- marginLeft: theme.spacing(3) + 40,
marginRight: theme.spacing(2),
+ marginLeft: theme.spacing(3) + 40,
+ },
+ title: {
+ ...theme.typography.h5,
+ },
+ id: {
+ ...theme.typography.subtitle1,
+ marginLeft: theme.spacing(1),
},
container: {
display: 'flex',
@@ -36,11 +42,11 @@ const useStyles = makeStyles((theme) => ({
marginRight: theme.spacing(2),
minWidth: 400,
},
- sidebar: {
+ rightSidebar: {
marginTop: theme.spacing(2),
flex: '0 0 200px',
},
- sidebarTitle: {
+ rightSidebarTitle: {
fontWeight: 'bold',
},
labelList: {
@@ -76,7 +82,6 @@ function Bug({ bug }: Props) {
<div className={classes.header}>
<BugTitleForm bug={bug} />
</div>
-
<div className={classes.container}>
<div className={classes.timeline}>
<TimelineQuery bug={bug} />
@@ -88,8 +93,8 @@ function Bug({ bug }: Props) {
)}
</IfLoggedIn>
</div>
- <div className={classes.sidebar}>
- <span className={classes.sidebarTitle}>Labels</span>
+ <div className={classes.rightSidebar}>
+ <span className={classes.rightSidebarTitle}>Labels</span>
<ul className={classes.labelList}>
{bug.labels.length === 0 && (
<span className={classes.noLabel}>None yet</span>
diff --git a/webui/src/pages/bug/BugQuery.tsx b/webui/src/pages/bug/BugQuery.tsx
index 2a70a2f8..5d459c42 100644
--- a/webui/src/pages/bug/BugQuery.tsx
+++ b/webui/src/pages/bug/BugQuery.tsx
@@ -3,6 +3,8 @@ import { RouteComponentProps } from 'react-router-dom';
import CircularProgress from '@material-ui/core/CircularProgress';
+import NotFoundPage from '../notfound/NotFoundPage';
+
import Bug from './Bug';
import { useGetBugQuery } from './BugQuery.generated';
@@ -15,8 +17,8 @@ const BugQuery: React.FC<Props> = ({ match }: Props) => {
variables: { id: match.params.id },
});
if (loading) return <CircularProgress />;
+ if (!data?.repository?.bug) return <NotFoundPage />;
if (error) return <p>Error: {error}</p>;
- if (!data?.repository?.bug) return <p>404.</p>;
return <Bug bug={data.repository.bug} />;
};
diff --git a/webui/src/pages/bug/CommentForm.tsx b/webui/src/pages/bug/CommentForm.tsx
index fe9536ac..e70348a6 100644
--- a/webui/src/pages/bug/CommentForm.tsx
+++ b/webui/src/pages/bug/CommentForm.tsx
@@ -27,6 +27,7 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
},
actions: {
display: 'flex',
+ gap: '1em',
justifyContent: 'flex-end',
},
greenButton: {
diff --git a/webui/src/pages/list/BugRow.graphql b/webui/src/pages/list/BugRow.graphql
index 547c09d8..e4e2760c 100644
--- a/webui/src/pages/list/BugRow.graphql
+++ b/webui/src/pages/list/BugRow.graphql
@@ -9,5 +9,8 @@ fragment BugRow on Bug {
labels {
...Label
}
+ comments {
+ totalCount
+ }
...authored
}
diff --git a/webui/src/pages/list/BugRow.tsx b/webui/src/pages/list/BugRow.tsx
index 8d8fb5cb..1f5d22aa 100644
--- a/webui/src/pages/list/BugRow.tsx
+++ b/webui/src/pages/list/BugRow.tsx
@@ -6,6 +6,7 @@ import TableRow from '@material-ui/core/TableRow/TableRow';
import Tooltip from '@material-ui/core/Tooltip/Tooltip';
import { makeStyles } from '@material-ui/core/styles';
import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
+import CommentOutlinedIcon from '@material-ui/icons/CommentOutlined';
import ErrorOutline from '@material-ui/icons/ErrorOutline';
import Date from 'src/components/Date';
@@ -74,6 +75,13 @@ const useStyles = makeStyles((theme) => ({
display: 'inline-block',
},
},
+ commentCount: {
+ fontSize: '1rem',
+ marginLeft: theme.spacing(0.5),
+ },
+ commentCountCell: {
+ display: 'inline-flex',
+ },
}));
type Props = {
@@ -82,6 +90,8 @@ type Props = {
function BugRow({ bug }: Props) {
const classes = useStyles();
+ // Subtract 1 from totalCount as 1 comment is the bug description
+ const commentCount = bug.comments.totalCount - 1;
return (
<TableRow hover>
<TableCell className={classes.cell}>
@@ -105,6 +115,12 @@ function BugRow({ bug }: Props) {
&nbsp;by {bug.author.displayName}
</div>
</div>
+ {commentCount > 0 && (
+ <span className={classes.commentCountCell}>
+ <CommentOutlinedIcon aria-label="Comment count" />
+ <span className={classes.commentCount}>{commentCount}</span>
+ </span>
+ )}
</TableCell>
</TableRow>
);
diff --git a/webui/src/pages/list/FilterToolbar.tsx b/webui/src/pages/list/FilterToolbar.tsx
index e4cd8e6a..74eefe4c 100644
--- a/webui/src/pages/list/FilterToolbar.tsx
+++ b/webui/src/pages/list/FilterToolbar.tsx
@@ -40,7 +40,7 @@ function CountingFilter({ query, children, ...props }: CountingFilterProps) {
variables: { query },
});
- var prefix;
+ let prefix;
if (loading) prefix = '...';
else if (error || !data?.repository) prefix = '???';
// TODO: better prefixes & error handling
diff --git a/webui/src/pages/new/NewBugPage.tsx b/webui/src/pages/new/NewBugPage.tsx
index 96afb56a..4dc60e3c 100644
--- a/webui/src/pages/new/NewBugPage.tsx
+++ b/webui/src/pages/new/NewBugPage.tsx
@@ -1,7 +1,7 @@
import React, { FormEvent, useState } from 'react';
+import { useHistory } from 'react-router-dom';
-import { Button } from '@material-ui/core';
-import Paper from '@material-ui/core/Paper';
+import { Button, Paper } from '@material-ui/core';
import { makeStyles, Theme } from '@material-ui/core/styles';
import BugTitleInput from '../../components/BugTitleForm/BugTitleInput';
@@ -47,7 +47,9 @@ function NewBugPage() {
const [issueTitle, setIssueTitle] = useState('');
const [issueComment, setIssueComment] = useState('');
const classes = useStyles();
+
let issueTitleInput: any;
+ let history = useHistory();
function submitNewIssue(e: FormEvent) {
e.preventDefault();
@@ -59,12 +61,15 @@ function NewBugPage() {
message: issueComment,
},
},
+ }).then(function (data) {
+ const id = data.data?.newBug.bug.humanId;
+ history.push('/bug/' + id);
});
issueTitleInput.value = '';
}
function isFormValid() {
- return issueTitle.length > 0 && issueComment.length > 0 ? true : false;
+ return issueTitle.length > 0;
}
if (loading) return <div>Loading...</div>;
diff --git a/webui/src/pages/notfound/NotFoundPage.tsx b/webui/src/pages/notfound/NotFoundPage.tsx
new file mode 100644
index 00000000..2c6f6854
--- /dev/null
+++ b/webui/src/pages/notfound/NotFoundPage.tsx
@@ -0,0 +1,52 @@
+import React from 'react';
+
+import { makeStyles } from '@material-ui/core/styles';
+
+import BackToListButton from '../../components/BackToListButton';
+
+const useStyles = makeStyles((theme) => ({
+ main: {
+ maxWidth: 1000,
+ margin: 'auto',
+ marginTop: theme.spacing(10),
+ },
+ logo: {
+ height: '350px',
+ display: 'block',
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ },
+ icon: {
+ display: 'block',
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ fontSize: '80px',
+ },
+ backLink: {
+ marginTop: theme.spacing(1),
+ textAlign: 'center',
+ },
+ header: {
+ fontSize: '30px',
+ textAlign: 'center',
+ },
+}));
+
+function NotFoundPage() {
+ const classes = useStyles();
+ return (
+ <main className={classes.main}>
+ <h1 className={classes.header}>404 – Page not found</h1>
+ <img
+ src="/logo-alpha-flat-outline.svg"
+ className={classes.logo}
+ alt="git-bug Logo"
+ />
+ <div className={classes.backLink}>
+ <BackToListButton />
+ </div>
+ </main>
+ );
+}
+
+export default NotFoundPage;
diff --git a/webui/src/themes/DefaultDark.ts b/webui/src/themes/DefaultDark.ts
index 6a92ec49..65dd6329 100644
--- a/webui/src/themes/DefaultDark.ts
+++ b/webui/src/themes/DefaultDark.ts
@@ -4,7 +4,8 @@ const defaultDarkTheme = createMuiTheme({
palette: {
type: 'dark',
primary: {
- main: '#263238',
+ dark: '#263238',
+ main: '#2a393e',
light: '#525252',
},
error: {
diff --git a/webui/src/themes/DefaultLight.ts b/webui/src/themes/DefaultLight.ts
index bc788a98..9c57ebe5 100644
--- a/webui/src/themes/DefaultLight.ts
+++ b/webui/src/themes/DefaultLight.ts
@@ -4,8 +4,10 @@ const defaultLightTheme = createMuiTheme({
palette: {
type: 'light',
primary: {
- main: '#263238',
+ dark: '#263238',
+ main: '#5a6b73',
light: '#f5f5f5',
+ contrastText: '#fff',
},
info: {
main: '#e2f1ff',