mirror of
https://github.com/MichaelMure/git-bug.git
synced 2024-12-15 18:23:08 +03:00
Merge pull request #600 from GlancingMind/upstream-improve-navigation
WebUI: Improve navigation
This commit is contained in:
commit
52df5a1f11
21
webui/public/logo-alpha-flat-outline.svg
Normal file
21
webui/public/logo-alpha-flat-outline.svg
Normal file
@ -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>
|
After Width: | Height: | Size: 6.1 KiB |
@ -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>
|
||||
);
|
||||
|
36
webui/src/components/BackToListButton.tsx
Normal file
36
webui/src/components/BackToListButton.tsx
Normal file
@ -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;
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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} />;
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
|
||||
},
|
||||
actions: {
|
||||
display: 'flex',
|
||||
gap: '1em',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
greenButton: {
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
52
webui/src/pages/notfound/NotFoundPage.tsx
Normal file
52
webui/src/pages/notfound/NotFoundPage.tsx
Normal file
@ -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;
|
@ -4,7 +4,8 @@ const defaultDarkTheme = createMuiTheme({
|
||||
palette: {
|
||||
type: 'dark',
|
||||
primary: {
|
||||
main: '#263238',
|
||||
dark: '#263238',
|
||||
main: '#2a393e',
|
||||
light: '#525252',
|
||||
},
|
||||
error: {
|
||||
|
@ -4,8 +4,10 @@ const defaultLightTheme = createMuiTheme({
|
||||
palette: {
|
||||
type: 'light',
|
||||
primary: {
|
||||
main: '#263238',
|
||||
dark: '#263238',
|
||||
main: '#5a6b73',
|
||||
light: '#f5f5f5',
|
||||
contrastText: '#fff',
|
||||
},
|
||||
info: {
|
||||
main: '#e2f1ff',
|
||||
|
Loading…
Reference in New Issue
Block a user