aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Gliech <quentingliech@gmail.com>2019-04-10 21:19:45 +0200
committerQuentin Gliech <quentingliech@gmail.com>2019-05-22 19:52:01 +0200
commitd79ef7a7945ba82caeec62cad44dad134c9edfbc (patch)
tree392d9ceaead2a5780862ecf89cf1cc2a0c550ed7
parent1a7ccd594adc6f185115ce12a4368c55ff418678 (diff)
downloadgit-bug-d79ef7a7945ba82caeec62cad44dad134c9edfbc.tar.gz
webui: Migrate to Material-UI's new style API
-rw-r--r--webui/src/App.js48
-rw-r--r--webui/src/Label.js21
-rw-r--r--webui/src/bug/Bug.js65
-rw-r--r--webui/src/bug/LabelChange.js13
-rw-r--r--webui/src/bug/Message.js43
-rw-r--r--webui/src/bug/SetStatus.js13
-rw-r--r--webui/src/bug/SetTitle.js13
-rw-r--r--webui/src/bug/Timeline.js60
-rw-r--r--webui/src/index.js19
-rw-r--r--webui/src/list/BugRow.js67
10 files changed, 189 insertions, 173 deletions
diff --git a/webui/src/App.js b/webui/src/App.js
index 3a693dcb..b2eb6bf0 100644
--- a/webui/src/App.js
+++ b/webui/src/App.js
@@ -1,39 +1,39 @@
import AppBar from '@material-ui/core/AppBar';
import CssBaseline from '@material-ui/core/CssBaseline';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import Toolbar from '@material-ui/core/Toolbar';
-import Typography from '@material-ui/core/Typography';
import React from 'react';
-import { Route, Switch, withRouter } from 'react-router';
+import { Route, Switch } from 'react-router';
import { Link } from 'react-router-dom';
import BugQuery from './bug/BugQuery';
import ListQuery from './list/ListQuery';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
appTitle: {
+ ...theme.typography.title,
color: 'white',
textDecoration: 'none',
},
-});
+}));
-const App = ({ location, classes }) => (
- <React.Fragment>
- <CssBaseline />
- <AppBar position="static" color="primary">
- <Toolbar>
- <Link to="/" className={classes.appTitle}>
- <Typography variant="title" color="inherit">
- git-bug webui
- </Typography>
- </Link>
- </Toolbar>
- </AppBar>
- <Switch>
- <Route path="/" exact component={ListQuery} />
- <Route path="/bug/:id" exact component={BugQuery} />
- </Switch>
- </React.Fragment>
-);
+export default function App() {
+ const classes = useStyles();
-export default withStyles(styles)(withRouter(App));
+ return (
+ <>
+ <CssBaseline />
+ <AppBar position="static" color="primary">
+ <Toolbar>
+ <Link to="/" className={classes.appTitle}>
+ git-bug webui
+ </Link>
+ </Toolbar>
+ </AppBar>
+ <Switch>
+ <Route path="/" exact component={ListQuery} />
+ <Route path="/bug/:id" exact component={BugQuery} />
+ </Switch>
+ </>
+ );
+}
diff --git a/webui/src/Label.js b/webui/src/Label.js
index e7c25c23..826d21f5 100644
--- a/webui/src/Label.js
+++ b/webui/src/Label.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import {
getContrastRatio,
darken,
@@ -42,7 +42,7 @@ const _genStyle = background => ({
// Generate a style object (text, background and border colors) from the label
const genStyle = label => _genStyle(getColor(label));
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
label: {
...theme.typography.body2,
padding: '0 6px',
@@ -53,12 +53,15 @@ const styles = theme => ({
borderBottom: 'solid 1.5px',
verticalAlign: 'bottom',
},
-});
+}));
-const Label = ({ label, classes }) => (
- <span className={classes.label} style={genStyle(label)}>
- {label}
- </span>
-);
+function Label({ label }) {
+ const classes = useStyles();
+ return (
+ <span className={classes.label} style={genStyle(label)}>
+ {label}
+ </span>
+ );
+}
-export default withStyles(styles)(Label);
+export default Label;
diff --git a/webui/src/bug/Bug.js b/webui/src/bug/Bug.js
index 9b5f84ad..829a4af2 100644
--- a/webui/src/bug/Bug.js
+++ b/webui/src/bug/Bug.js
@@ -1,4 +1,4 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import Typography from '@material-ui/core/Typography/Typography';
import gql from 'graphql-tag';
import React from 'react';
@@ -7,7 +7,7 @@ import Date from '../Date';
import TimelineQuery from './TimelineQuery';
import Label from '../Label';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
main: {
maxWidth: 800,
margin: 'auto',
@@ -48,38 +48,41 @@ const styles = theme => ({
display: 'block',
},
},
-});
+}));
-const Bug = ({ bug, classes }) => (
- <main className={classes.main}>
- <div className={classes.header}>
- <span className={classes.title}>{bug.title}</span>
- <span className={classes.id}>{bug.humanId}</span>
+function Bug({ bug }) {
+ 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>
- </div>
-
- <div className={classes.container}>
- <div className={classes.timeline}>
- <TimelineQuery id={bug.id} />
+ <Typography color={'textSecondary'}>
+ <Author author={bug.author} />
+ {' opened this bug '}
+ <Date date={bug.createdAt} />
+ </Typography>
</div>
- <div className={classes.sidebar}>
- <Typography variant={'subheading'}>Labels</Typography>
- <ul className={classes.labelList}>
- {bug.labels.map(l => (
- <li className={classes.label}>
- <Label label={l} key={l} />
- </li>
- ))}
- </ul>
+
+ <div className={classes.container}>
+ <div className={classes.timeline}>
+ <TimelineQuery id={bug.id} />
+ </div>
+ <div className={classes.sidebar}>
+ <Typography variant={'subheading'}>Labels</Typography>
+ <ul className={classes.labelList}>
+ {bug.labels.map(l => (
+ <li className={classes.label}>
+ <Label label={l} key={l} />
+ </li>
+ ))}
+ </ul>
+ </div>
</div>
- </div>
- </main>
-);
+ </main>
+ );
+}
Bug.fragment = gql`
fragment Bug on Bug {
@@ -97,4 +100,4 @@ Bug.fragment = gql`
}
`;
-export default withStyles(styles)(Bug);
+export default Bug;
diff --git a/webui/src/bug/LabelChange.js b/webui/src/bug/LabelChange.js
index 6301f35f..76b6e6e2 100644
--- a/webui/src/bug/LabelChange.js
+++ b/webui/src/bug/LabelChange.js
@@ -1,11 +1,11 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import gql from 'graphql-tag';
import React from 'react';
import Author from '../Author';
import Date from '../Date';
import Label from '../Label';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body2,
marginLeft: theme.spacing.unit + 40,
@@ -13,10 +13,11 @@ const styles = theme => ({
author: {
fontWeight: 'bold',
},
-});
+}));
-const LabelChange = ({ op, classes }) => {
+function LabelChange({ op }) {
const { added, removed } = op;
+ const classes = useStyles();
return (
<div className={classes.main}>
<Author author={op.author} className={classes.author} />
@@ -37,7 +38,7 @@ const LabelChange = ({ op, classes }) => {
<Date date={op.date} />
</div>
);
-};
+}
LabelChange.fragment = gql`
fragment LabelChange on TimelineItem {
@@ -54,4 +55,4 @@ LabelChange.fragment = gql`
}
`;
-export default withStyles(styles)(LabelChange);
+export default LabelChange;
diff --git a/webui/src/bug/Message.js b/webui/src/bug/Message.js
index 493de8ee..ff039444 100644
--- a/webui/src/bug/Message.js
+++ b/webui/src/bug/Message.js
@@ -1,4 +1,4 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import Paper from '@material-ui/core/Paper';
import gql from 'graphql-tag';
import React from 'react';
@@ -6,7 +6,7 @@ import Author from '../Author';
import { Avatar } from '../Author';
import Date from '../Date';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
author: {
fontWeight: 'bold',
},
@@ -44,24 +44,27 @@ const styles = theme => ({
padding: '1rem',
whiteSpace: 'pre-wrap',
},
-});
+}));
-const Message = ({ op, classes }) => (
- <article className={classes.container}>
- <Avatar author={op.author} className={classes.avatar} />
- <Paper elevation={1} className={classes.bubble}>
- <header className={classes.header}>
- <div className={classes.title}>
- <Author className={classes.author} author={op.author} />
- <span> commented </span>
- <Date date={op.createdAt} />
- </div>
- {op.edited && <div className={classes.tag}>Edited</div>}
- </header>
- <section className={classes.body}>{op.message}</section>
- </Paper>
- </article>
-);
+function Message({ op }) {
+ const classes = useStyles();
+ return (
+ <article className={classes.container}>
+ <Avatar author={op.author} className={classes.avatar} />
+ <Paper elevation={1} className={classes.bubble}>
+ <header className={classes.header}>
+ <div className={classes.title}>
+ <Author className={classes.author} author={op.author} />
+ <span> commented </span>
+ <Date date={op.createdAt} />
+ </div>
+ {op.edited && <div className={classes.tag}>Edited</div>}
+ </header>
+ <section className={classes.body}>{op.message}</section>
+ </Paper>
+ </article>
+ );
+}
Message.createFragment = gql`
fragment Create on TimelineItem {
@@ -95,4 +98,4 @@ Message.commentFragment = gql`
}
`;
-export default withStyles(styles)(Message);
+export default Message;
diff --git a/webui/src/bug/SetStatus.js b/webui/src/bug/SetStatus.js
index 58b81630..ab591038 100644
--- a/webui/src/bug/SetStatus.js
+++ b/webui/src/bug/SetStatus.js
@@ -1,17 +1,18 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import gql from 'graphql-tag';
import React from 'react';
import Author from '../Author';
import Date from '../Date';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body2,
marginLeft: theme.spacing.unit + 40,
},
-});
+}));
-const SetStatus = ({ op, classes }) => {
+function SetStatus({ op }) {
+ const classes = useStyles();
return (
<div className={classes.main}>
<Author author={op.author} bold />
@@ -19,7 +20,7 @@ const SetStatus = ({ op, classes }) => {
<Date date={op.date} />
</div>
);
-};
+}
SetStatus.fragment = gql`
fragment SetStatus on TimelineItem {
@@ -35,4 +36,4 @@ SetStatus.fragment = gql`
}
`;
-export default withStyles(styles)(SetStatus);
+export default SetStatus;
diff --git a/webui/src/bug/SetTitle.js b/webui/src/bug/SetTitle.js
index f5c48568..d9a09ad5 100644
--- a/webui/src/bug/SetTitle.js
+++ b/webui/src/bug/SetTitle.js
@@ -1,10 +1,10 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import gql from 'graphql-tag';
import React from 'react';
import Author from '../Author';
import Date from '../Date';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body2,
marginLeft: theme.spacing.unit + 40,
@@ -12,9 +12,10 @@ const styles = theme => ({
bold: {
fontWeight: 'bold',
},
-});
+}));
-const SetTitle = ({ op, classes }) => {
+function SetTitle({ op }) {
+ const classes = useStyles();
return (
<div className={classes.main}>
<Author author={op.author} className={classes.bold} />
@@ -25,7 +26,7 @@ const SetTitle = ({ op, classes }) => {
<Date date={op.date} />
</div>
);
-};
+}
SetTitle.fragment = gql`
fragment SetTitle on TimelineItem {
@@ -42,4 +43,4 @@ SetTitle.fragment = gql`
}
`;
-export default withStyles(styles)(SetTitle);
+export default SetTitle;
diff --git a/webui/src/bug/Timeline.js b/webui/src/bug/Timeline.js
index 3123f45f..d77e0d4b 100644
--- a/webui/src/bug/Timeline.js
+++ b/webui/src/bug/Timeline.js
@@ -1,51 +1,43 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import React from 'react';
import LabelChange from './LabelChange';
import Message from './Message';
import SetStatus from './SetStatus';
import SetTitle from './SetTitle';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
main: {
'& > *:not(:last-child)': {
marginBottom: theme.spacing.unit * 2,
},
},
-});
+}));
-class Timeline extends React.Component {
- props: {
- ops: Array,
- fetchMore: any => any,
- classes: any,
- };
+const componentMap = {
+ CreateTimelineItem: Message,
+ AddCommentTimelineItem: Message,
+ LabelChangeTimelineItem: LabelChange,
+ SetTitleTimelineItem: SetTitle,
+ SetStatusTimelineItem: SetStatus,
+};
- render() {
- const { ops, classes } = this.props;
+function Timeline({ ops }) {
+ const classes = useStyles();
- return (
- <div className={classes.main}>
- {ops.map((op, index) => {
- switch (op.__typename) {
- case 'CreateTimelineItem':
- return <Message key={index} op={op} />;
- case 'AddCommentTimelineItem':
- return <Message key={index} op={op} />;
- case 'LabelChangeTimelineItem':
- return <LabelChange key={index} op={op} />;
- case 'SetTitleTimelineItem':
- return <SetTitle key={index} op={op} />;
- case 'SetStatusTimelineItem':
- return <SetStatus key={index} op={op} />;
+ return (
+ <div className={classes.main}>
+ {ops.map((op, index) => {
+ const Component = componentMap[op.__typename];
- default:
- console.log('unsupported operation type ' + op.__typename);
- return null;
- }
- })}
- </div>
- );
- }
+ if (!Component) {
+ console.warn('unsupported operation type ' + op.__typename);
+ return null;
+ }
+
+ return <Component key={index} op={op} />;
+ })}
+ </div>
+ );
}
-export default withStyles(styles)(Timeline);
+export default Timeline;
diff --git a/webui/src/index.js b/webui/src/index.js
index f5d95ccc..885911f5 100644
--- a/webui/src/index.js
+++ b/webui/src/index.js
@@ -1,22 +1,31 @@
+import { install } from '@material-ui/styles';
+import ThemeProvider from '@material-ui/styles/ThemeProvider';
+import { createMuiTheme } from '@material-ui/core/styles';
import ApolloClient from 'apollo-boost';
import React from 'react';
import { ApolloProvider } from 'react-apollo';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
-import App from './App';
+install();
+
+// TODO(sandhose): this is temporary until Material-UI v4 goes out
+const App = React.lazy(() => import('./App'));
+
+const theme = createMuiTheme();
const client = new ApolloClient({
uri: '/graphql',
- connectToDevTools: true,
});
ReactDOM.render(
<ApolloProvider client={client}>
<BrowserRouter>
- <React.Fragment>
- <App />
- </React.Fragment>
+ <ThemeProvider theme={theme}>
+ <React.Suspense fallback={'Loading…'}>
+ <App />
+ </React.Suspense>
+ </ThemeProvider>
</BrowserRouter>
</ApolloProvider>,
document.getElementById('root')
diff --git a/webui/src/list/BugRow.js b/webui/src/list/BugRow.js
index a045770b..e82d81db 100644
--- a/webui/src/list/BugRow.js
+++ b/webui/src/list/BugRow.js
@@ -1,4 +1,4 @@
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/styles';
import TableCell from '@material-ui/core/TableCell/TableCell';
import TableRow from '@material-ui/core/TableRow/TableRow';
import Tooltip from '@material-ui/core/Tooltip/Tooltip';
@@ -33,7 +33,7 @@ const Status = ({ status, className }) => {
}
};
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
cell: {
display: 'flex',
alignItems: 'center',
@@ -53,36 +53,39 @@ const styles = theme => ({
labels: {
paddingLeft: theme.spacing.unit,
},
-});
+}));
-const BugRow = ({ bug, classes }) => (
- <TableRow hover>
- <TableCell className={classes.cell}>
- <Status status={bug.status} className={classes.status} />
- <div className={classes.expand}>
- <Link to={'bug/' + bug.humanId}>
- <div className={classes.expand}>
- <Typography variant={'title'} className={classes.title}>
- {bug.title}
- </Typography>
- {bug.labels.length > 0 && (
- <span className={classes.labels}>
- {bug.labels.map(l => (
- <Label key={l} label={l} />
- ))}
- </span>
- )}
- </div>
- </Link>
- <Typography color={'textSecondary'}>
- {bug.humanId} opened
- <Date date={bug.createdAt} />
- by {bug.author.displayName}
- </Typography>
- </div>
- </TableCell>
- </TableRow>
-);
+function BugRow({ bug }) {
+ const classes = useStyles();
+ return (
+ <TableRow hover>
+ <TableCell className={classes.cell}>
+ <Status status={bug.status} className={classes.status} />
+ <div className={classes.expand}>
+ <Link to={'bug/' + bug.humanId}>
+ <div className={classes.expand}>
+ <Typography variant={'title'} className={classes.title}>
+ {bug.title}
+ </Typography>
+ {bug.labels.length > 0 && (
+ <span className={classes.labels}>
+ {bug.labels.map(l => (
+ <Label key={l} label={l} />
+ ))}
+ </span>
+ )}
+ </div>
+ </Link>
+ <Typography color={'textSecondary'}>
+ {bug.humanId} opened
+ <Date date={bug.createdAt} />
+ by {bug.author.displayName}
+ </Typography>
+ </div>
+ </TableCell>
+ </TableRow>
+ );
+}
BugRow.fragment = gql`
fragment BugRow on Bug {
@@ -99,4 +102,4 @@ BugRow.fragment = gql`
}
`;
-export default withStyles(styles)(BugRow);
+export default BugRow;