diff options
author | Michael Muré <batolettre@gmail.com> | 2021-03-21 21:31:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-21 21:31:14 +0100 |
commit | 52df5a1f1199d085b2bb10fb7ed5599dcb8307c4 (patch) | |
tree | 031a10e135ceb60c623aca994db9c4c701b7ef66 /webui | |
parent | 6744cddaa6ed25b9f2c0c61ef9df1823b5e74e6e (diff) | |
parent | aeb26d0e84b14a44ed52e2fd158b01310e295e45 (diff) | |
download | git-bug-52df5a1f1199d085b2bb10fb7ed5599dcb8307c4.tar.gz |
Merge pull request #600 from GlancingMind/upstream-improve-navigation
WebUI: Improve navigation
Diffstat (limited to 'webui')
-rw-r--r-- | webui/public/logo-alpha-flat-outline.svg | 21 | ||||
-rw-r--r-- | webui/src/App.tsx | 2 | ||||
-rw-r--r-- | webui/src/components/BackToListButton.tsx | 36 | ||||
-rw-r--r-- | webui/src/components/BugTitleForm/BugTitleForm.tsx | 2 | ||||
-rw-r--r-- | webui/src/components/Content/PreTag.tsx | 2 | ||||
-rw-r--r-- | webui/src/components/Header/Header.tsx | 73 | ||||
-rw-r--r-- | webui/src/pages/bug/Bug.tsx | 19 | ||||
-rw-r--r-- | webui/src/pages/bug/BugQuery.tsx | 4 | ||||
-rw-r--r-- | webui/src/pages/bug/CommentForm.tsx | 1 | ||||
-rw-r--r-- | webui/src/pages/list/FilterToolbar.tsx | 2 | ||||
-rw-r--r-- | webui/src/pages/new/NewBugPage.tsx | 11 | ||||
-rw-r--r-- | webui/src/pages/notfound/NotFoundPage.tsx | 52 | ||||
-rw-r--r-- | webui/src/themes/DefaultDark.ts | 3 | ||||
-rw-r--r-- | webui/src/themes/DefaultLight.ts | 4 |
14 files changed, 210 insertions, 22 deletions
diff --git a/webui/public/logo-alpha-flat-outline.svg b/webui/public/logo-alpha-flat-outline.svg new file mode 100644 index 00000000..ea383f3c --- /dev/null +++ b/webui/public/logo-alpha-flat-outline.svg @@ -0,0 +1,21 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024"> + <defs> + <path id="b" d="M512.169916 1006.61442c-59.127025 0-118.268018-11.781213-172.799806-34.617561-54.406082-22.780496-104.066777-56.504427-145.315673-98.654977-20.922999-21.380714-39.670593-44.876809-55.890107-70.010056-17.752424-27.503453-33.154852-57.048981-43.3125626-88.22468-22.4244822-68.819718-19.4215151-144.704671 8.7854246-211.391554 26.454045-62.532915 73.778712-115.431419 133.345707-148.122094 7.140776-3.916598 14.438685-7.546956 21.869283-10.877111 1.581795-22.420951 7.259498-44.632458 15.35005-65.555887 8.062618-20.853613 18.635855-41.190599 32.313323-58.926992l-45.425115-45.365511c-25.284285 1.612716-50.236847-9.407515-66.183999-29.060318-15.870332-19.558553-21.457247-46.1579063-14.75644-70.4463972 6.473838-23.4786418 24.027228-43.0790839 46.615826-52.1759231 23.259028-9.3656253 50.268273-6.8837172 71.435699 6.5416257 24.04818 15.2579756 38.322749 42.9953065 36.534936 71.4447456l49.377858 49.310035c38.850014-22.675774 83.39519-34.258012 128.055596-34.331317 44.660406.073305 89.205582 11.655543 128.059088 34.331317l49.374366-49.310035c-1.787813-28.4494391 12.486757-56.18677 36.534936-71.4447456 21.167427-13.4253429 48.176671-15.907251 71.435699-6.5416257 22.588598 9.0968392 40.138497 28.6972813 46.615827 52.1759231 6.700807 24.2919816 1.113891 50.8878442-14.756441 70.4463972-15.947152 19.652803-40.899714 30.673034-66.18749 29.060318l-45.421623 45.365511c13.677467 17.736393 24.250705 38.073379 32.313322 58.926992 8.090552 20.923429 13.768255 43.134936 15.350051 65.555887 7.430598 3.330155 14.731998 6.960513 21.869282 10.877111 59.566996 32.690675 106.891662 85.59267 133.345707 148.125585 28.20694 66.683392 31.213399 142.568345 8.785425 211.388063-10.157711 31.175699-25.560139 60.721227-43.312563 88.22468-16.219514 25.133247-34.967108 48.629342-55.890106 70.010056-41.252388 42.15055-90.913084 75.874481-145.315674 98.654977-54.535279 22.836348-113.67278 34.617561-172.799806 34.617561"/> + <filter id="a" width="106%" height="105.3%" x="-3%" y="-2.2%" filterUnits="objectBoundingBox"> + <feOffset dy="4" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="8"/> + <feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"/> + </filter> + </defs> + <g fill="none" fill-rule="evenodd"> + <g fill-rule="nonzero"> + <use fill="#000" filter="url(#a)" xlink:href="#b"/> + <use fill="#FFF" xlink:href="#b"/> + </g> + <path fill="#D0021B" d="M120.388511 676.726932c4.109875 19.495721 10.395155 38.464341 18.695216 56.570751 62.793439 135.897562 197.675548 231.648253 355.628126 238.256202V392.229046l-86.684487 86.608471c2.007798 5.044104 3.14264 10.531529 3.14264 16.291232 0 18.162262-10.988764 33.751856-26.67403 40.516889v210.012716c15.685266 6.768523 26.67403 22.354627 26.67403 40.520379 0 24.368778-19.760222 44.119321-44.133141 44.119321-24.376411 0-44.136633-19.750543-44.136633-44.119321 0-18.165752 10.988765-33.751856 26.677522-40.520379V537.23741l-62.37442 62.319981c2.007797 5.040612 3.14264 10.524547 3.14264 16.280759 0 24.365287-19.760222 44.119321-44.133141 44.119321-24.376411 0-44.136633-19.754034-44.136633-44.119321 0-24.368778 19.760222-44.122812 44.136633-44.122812 5.764998 0 11.257635 1.137978 16.306809 3.148638l63.519738-63.46145c-2.004306-5.040612-3.139148-10.521056-3.139148-16.273777 0-24.368778 19.760222-44.122812 44.136633-44.122812 5.761507 0 11.254143 1.137977 16.299826 3.145147l111.375162-111.273962v-3.413933c-58.285497 1.124015-115.188232 7.857631-170.205383 19.680729-143.245022 32.174047-234.4758615 173.520637-204.117959 317.583014"/> + <path fill="#161616" d="M512.169916 150.665029c49.758467 0 95.630535 16.518128 132.511162 44.321783l82.55366-82.440542c-6.274804-15.7815846-2.786474-34.1393273 8.844786-46.4999979 10.552287-11.2122209 26.565784-16.165565 41.619029-12.8772985 14.718031 3.2184519 27.058131 14.1025443 32.114289 28.2853753 5.188848 14.5388854 2.234766 31.1547541-7.633123 43.0162511-12.102656 14.549357-32.662505 19.788941-50.271765 12.769086l-81.048685 80.939528c29.792227 30.913894 50.669832 70.474323 58.411202 114.579682-55.240628-13.338075-111.706885-21.541288-168.455979-24.511898-57.475394-3.009008-115.233625-.684183-172.272541 6.988439-31.433384 4.227273-62.643291 10.081225-93.469098 17.523459 7.737878-44.105359 28.615484-83.665788 58.404219-114.579682l-81.048686-80.939528c-15.79002 6.297274-34.181447 2.810036-46.552973-8.824563-11.219225-10.548982-16.174121-26.560955-12.884824-41.6059961 3.21946-14.7134218 14.106961-27.0496574 28.294235-32.1077234 14.54344-5.1837322 31.164513-2.2305757 43.029725 7.6342239 14.539948 12.0918845 19.784665 32.6173697 12.790545 50.2106426l82.553661 82.440542c36.884118-27.803655 82.752695-44.321783 132.511161-44.321783"/> + <path fill="#D0021B" d="M700.196272 359.235741c-55.01715-11.823099-111.916394-18.556715-170.20189-19.68422v3.413933l111.37167 111.277452c5.049175-2.007169 10.538319-3.148637 16.303318-3.148637 24.376411 0 44.136632 19.757525 44.136632 44.122812 0 5.756211-1.134842 11.233165-3.139148 16.273777l63.516246 63.46494c5.049175-2.01066 10.541812-3.148637 16.310302-3.148637 24.372919 0 44.136633 19.754034 44.136633 44.119321 0 24.368778-19.763714 44.122812-44.136633 44.122812-24.376411 0-44.136633-19.754034-44.136633-44.122812 0-5.756212 1.134842-11.240147 3.146132-16.280759l-62.377912-62.319981v208.424434c15.688757 6.765033 26.681013 22.354627 26.681013 40.52038 0 24.365287-19.760221 44.119321-44.136632 44.119321-24.372919 0-44.133141-19.754034-44.133141-44.119321 0-18.165753 10.985272-33.755347 26.670538-40.52038V535.73746c-15.685266-6.765032-26.670538-22.354627-26.670538-40.520379 0-5.759703 1.134842-11.247129 3.14264-16.287741l-86.684487-86.611963v579.32484c157.949086-6.604459 292.831195-102.35864 355.628126-238.252711 8.296569-18.109901 14.581849-37.078522 18.691724-56.570751 30.357902-144.065868-60.872937-285.408967-204.11796-317.583014"/> + </g> + <animate attributeName="opacity" attributeType="XML" + dur="5s" from="0" to="1" fill="freeze"/> +</svg> 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 d85c5296..3b6b61e0 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: { @@ -75,7 +81,6 @@ function Bug({ bug }: Props) { <div className={classes.header}> <BugTitleForm bug={bug} /> </div> - <div className={classes.container}> <div className={classes.timeline}> <TimelineQuery id={bug.id} /> @@ -87,8 +92,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 773e7d0e..6d27e398 100644 --- a/webui/src/pages/bug/CommentForm.tsx +++ b/webui/src/pages/bug/CommentForm.tsx @@ -28,6 +28,7 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({ }, actions: { display: 'flex', + gap: '1em', justifyContent: 'flex-end', }, greenButton: { 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', |