Detailed changes
  
  
    
    @@ -161,7 +161,7 @@ func (gi *githubImporter) ensureIssue(repo *cache.RepoCache, issue issueTimeline
 				b, _, err = repo.NewBugRaw(
 					author,
 					issue.CreatedAt.Unix(),
-					issue.Title,
+					issue.Title, // TODO: this is the *current* title, not the original one
 					cleanText,
 					nil,
 					map[string]string{
  
  
  
    
    @@ -29,9 +29,13 @@ module.exports = {
             position: 'after',
           },
         ],
-        groups: [['builtin', 'external'], 'parent', ['sibling', 'index']],
+        pathGroupsExcludedImportTypes: ["builtin"],
+        groups: [['builtin', 'external'], ['internal', 'parent'], ['sibling', 'index']],
         'newlines-between': 'always',
       },
     ],
   },
+  settings: {
+    'import/internal-regex': '^src/',
+  },
 };
  
  
  
    
    @@ -14608,6 +14608,11 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
       "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
     },
+    "react-moment": {
+      "version": "0.9.7",
+      "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz",
+      "integrity": "sha512-ifzUrUGF6KRsUN2pRG5k56kO0mJBr8kRkWb0wNvtFIsBIxOuPxhUpL1YlXwpbQCbHq23hUu6A0VEk64HsFxk9g=="
+    },
     "react-router": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
  
  
  
    
    @@ -21,6 +21,7 @@
     "react": "^16.8.6",
     "react-apollo": "^3.1.3",
     "react-dom": "^16.8.6",
+    "react-moment": "^0.9.7",
     "react-router": "^5.0.0",
     "react-router-dom": "^5.0.0",
     "react-scripts": "^3.3.1",
@@ -48,7 +49,8 @@
     "test": "react-scripts test --env=jsdom",
     "eject": "react-scripts eject",
     "generate": "graphql-codegen",
-    "lint": "eslint src --ext .ts --ext .tsx --ext .js --ext .jsx --ext .graphql"
+    "lint": "eslint src --ext .ts --ext .tsx --ext .js --ext .jsx --ext .graphql",
+    "clean": "rimraf src/**.generated.* src/schema.json src/gqlTypes.* src/fragmentTypes.*"
   },
   "proxy": "http://localhost:3001",
   "browserslist": [
  
  
  
    
    @@ -1,68 +1,17 @@
-import AppBar from '@material-ui/core/AppBar';
-import CssBaseline from '@material-ui/core/CssBaseline';
-import Toolbar from '@material-ui/core/Toolbar';
-import {
-  createMuiTheme,
-  ThemeProvider,
-  makeStyles,
-} from '@material-ui/core/styles';
 import React from 'react';
 import { Route, Switch } from 'react-router';
-import { Link } from 'react-router-dom';
 
-import CurrentIdentity from './CurrentIdentity';
-import BugQuery from './bug/BugQuery';
-import ListQuery from './list/ListQuery';
-
-const theme = createMuiTheme({
-  palette: {
-    primary: {
-      main: '#263238',
-    },
-  },
-});
-
-const useStyles = makeStyles(theme => ({
-  offset: {
-    ...theme.mixins.toolbar,
-  },
-  filler: {
-    flexGrow: 1,
-  },
-  appTitle: {
-    ...theme.typography.h6,
-    color: 'white',
-    textDecoration: 'none',
-    display: 'flex',
-    alignItems: 'center',
-  },
-  logo: {
-    height: '42px',
-    marginRight: theme.spacing(2),
-  },
-}));
+import Layout from './layout';
+import BugPage from './pages/bug';
+import ListPage from './pages/list';
 
 export default function App() {
-  const classes = useStyles();
-
   return (
-    <ThemeProvider theme={theme}>
-      <CssBaseline />
-      <AppBar position="fixed" color="primary">
-        <Toolbar>
-          <Link to="/" className={classes.appTitle}>
-            <img src="/logo.svg" className={classes.logo} alt="git-bug" />
-            git-bug
-          </Link>
-          <div className={classes.filler}></div>
-          <CurrentIdentity />
-        </Toolbar>
-      </AppBar>
-      <div className={classes.offset} />
+    <Layout>
       <Switch>
-        <Route path="/" exact component={ListQuery} />
-        <Route path="/bug/:id" exact component={BugQuery} />
+        <Route path="/" exact component={ListPage} />
+        <Route path="/bug/:id" exact component={BugPage} />
       </Switch>
-    </ThemeProvider>
+    </Layout>
   );
 }
  
  
  
    
    @@ -1,12 +0,0 @@
-import Tooltip from '@material-ui/core/Tooltip/Tooltip';
-import moment from 'moment';
-import React from 'react';
-
-type Props = { date: string };
-const Date = ({ date }: Props) => (
-  <Tooltip title={moment(date).format('MMMM D, YYYY, h:mm a')}>
-    <span> {moment(date).fromNow()} </span>
-  </Tooltip>
-);
-
-export default Date;
  
  
  
    
    @@ -1,8 +0,0 @@
-fragment Label on Label {
-  name
-  color {
-    R
-    G
-    B
-  }
-}
  
  
  
    
    @@ -1,4 +1,4 @@
-import { parse, stringify, quote } from '../list/Filter';
+import { parse, stringify, quote } from 'src/pages/list/Filter';
 
 it('parses a simple query', () => {
   expect(parse('foo:bar')).toEqual({
  
  
  
    
    @@ -0,0 +1,18 @@
+import ApolloClient from 'apollo-boost';
+import {
+  IntrospectionFragmentMatcher,
+  InMemoryCache,
+} from 'apollo-cache-inmemory';
+
+import introspectionQueryResultData from './fragmentTypes';
+
+const client = new ApolloClient({
+  uri: '/graphql',
+  cache: new InMemoryCache({
+    fragmentMatcher: new IntrospectionFragmentMatcher({
+      introspectionQueryResultData,
+    }),
+  }),
+});
+
+export default client;
  
  
  
    
    @@ -1,8 +1,9 @@
+import React from 'react';
+
 import MAvatar from '@material-ui/core/Avatar';
 import Tooltip from '@material-ui/core/Tooltip/Tooltip';
-import React from 'react';
 
-import { AuthoredFragment } from './Author.generated';
+import { AuthoredFragment } from './fragments.generated';
 
 type Props = AuthoredFragment & {
   className?: string;
  
  
  
    
    @@ -1,6 +1,7 @@
-import { makeStyles } from '@material-ui/styles';
 import React from 'react';
 
+import { makeStyles } from '@material-ui/styles';
+
 const useStyles = makeStyles({
   tag: {
     maxWidth: '100%',
  
  
  
    
    @@ -1,6 +1,7 @@
-import { makeStyles } from '@material-ui/styles';
 import React from 'react';
 
+import { makeStyles } from '@material-ui/styles';
+
 const useStyles = makeStyles({
   tag: {
     maxWidth: '100%',
  
  
  
    
    @@ -4,8 +4,8 @@ import parse from 'remark-parse';
 import remark2react from 'remark-react';
 import unified from 'unified';
 
-import ImageTag from './tag/ImageTag';
-import PreTag from './tag/PreTag';
+import ImageTag from './ImageTag';
+import PreTag from './PreTag';
 
 type Props = { markdown: string };
 const Content: React.FC<Props> = ({ markdown }: Props) => {
  
  
  
    
    @@ -0,0 +1,20 @@
+import moment from 'moment';
+import React from 'react';
+import Moment from 'react-moment';
+
+import Tooltip from '@material-ui/core/Tooltip/Tooltip';
+
+const HOUR = 1000 * 3600;
+const DAY = 24 * HOUR;
+const WEEK = 7 * DAY;
+
+type Props = { date: string };
+const Date = ({ date }: Props) => (
+  <Tooltip title={moment(date).format('LLLL')}>
+    <span>
+      on <Moment date={date} format="ll" fromNowDuring={WEEK} />
+    </span>
+  </Tooltip>
+);
+
+export default Date;
  
  
  
    
    @@ -1,13 +1,15 @@
+import React from 'react';
+
 import { common } from '@material-ui/core/colors';
 import { makeStyles } from '@material-ui/core/styles';
 import {
   getContrastRatio,
   darken,
 } from '@material-ui/core/styles/colorManipulator';
-import React from 'react';
 
-import { LabelFragment } from './Label.generated';
-import { Color } from './gqlTypes';
+import { Color } from 'src/gqlTypes';
+
+import { LabelFragment } from './fragments.generated';
 
 // Minimum contrast between the background and the text color
 const contrastThreshold = 2.5;
  
  
  
    
    @@ -1,3 +1,14 @@
+# Label.tsx
+fragment Label on Label {
+  name
+  color {
+    R
+    G
+    B
+  }
+}
+
+# Author.tsx
 fragment authored on Authored {
   author {
     name
  
  
  
    
    @@ -1,36 +1,19 @@
-import { createMuiTheme } from '@material-ui/core/styles';
-import ThemeProvider from '@material-ui/styles/ThemeProvider';
-import ApolloClient from 'apollo-boost';
-import {
-  IntrospectionFragmentMatcher,
-  InMemoryCache,
-} from 'apollo-cache-inmemory';
 import React from 'react';
 import { ApolloProvider } from 'react-apollo';
 import ReactDOM from 'react-dom';
 import { BrowserRouter } from 'react-router-dom';
 
-import App from './App';
-import introspectionQueryResultData from './fragmentTypes';
-
-const theme = createMuiTheme();
+import ThemeProvider from '@material-ui/styles/ThemeProvider';
 
-const client = new ApolloClient({
-  uri: '/graphql',
-  cache: new InMemoryCache({
-    fragmentMatcher: new IntrospectionFragmentMatcher({
-      introspectionQueryResultData,
-    }),
-  }),
-});
+import App from './App';
+import apolloClient from './apollo';
+import theme from './theme';
 
 ReactDOM.render(
-  <ApolloProvider client={client}>
+  <ApolloProvider client={apolloClient}>
     <BrowserRouter>
       <ThemeProvider theme={theme}>
-        <React.Suspense fallback={'Loadingβ¦'}>
-          <App />
-        </React.Suspense>
+        <App />
       </ThemeProvider>
     </BrowserRouter>
   </ApolloProvider>,
  
  
  
    
    
  
  
  
    
    @@ -1,6 +1,7 @@
+import React from 'react';
+
 import Avatar from '@material-ui/core/Avatar';
 import { makeStyles } from '@material-ui/core/styles';
-import React from 'react';
 
 import { useCurrentIdentityQuery } from './CurrentIdentity.generated';
 
  
  
  
    
    @@ -0,0 +1,50 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+
+import AppBar from '@material-ui/core/AppBar';
+import Toolbar from '@material-ui/core/Toolbar';
+import { makeStyles } from '@material-ui/core/styles';
+
+import CurrentIdentity from './CurrentIdentity';
+
+const useStyles = makeStyles(theme => ({
+  offset: {
+    ...theme.mixins.toolbar,
+  },
+  filler: {
+    flexGrow: 1,
+  },
+  appTitle: {
+    ...theme.typography.h6,
+    color: 'white',
+    textDecoration: 'none',
+    display: 'flex',
+    alignItems: 'center',
+  },
+  logo: {
+    height: '42px',
+    marginRight: theme.spacing(2),
+  },
+}));
+
+function Header() {
+  const classes = useStyles();
+
+  return (
+    <>
+      <AppBar position="fixed" color="primary">
+        <Toolbar>
+          <Link to="/" className={classes.appTitle}>
+            <img src="/logo.svg" className={classes.logo} alt="git-bug" />
+            git-bug
+          </Link>
+          <div className={classes.filler}></div>
+          <CurrentIdentity />
+        </Toolbar>
+      </AppBar>
+      <div className={classes.offset} />
+    </>
+  );
+}
+
+export default Header;
  
  
  
    
    @@ -0,0 +1,18 @@
+import React from 'react';
+
+import CssBaseline from '@material-ui/core/CssBaseline';
+
+import Header from './Header';
+
+type Props = { children: React.ReactNode };
+function Layout({ children }: Props) {
+  return (
+    <>
+      <CssBaseline />
+      <Header />
+      {children}
+    </>
+  );
+}
+
+export default Layout;
  
  
  
    
    @@ -1,5 +1,4 @@
-#import "../Label.graphql"
-#import "../Author.graphql"
+#import "../components/fragments.graphql"
 
 fragment Bug on Bug {
   id
  
  
  
    
    @@ -1,17 +1,19 @@
+import React from 'react';
+
 import Typography from '@material-ui/core/Typography/Typography';
 import { makeStyles } from '@material-ui/core/styles';
-import React from 'react';
 
-import Author from '../Author';
-import Date from '../Date';
-import Label from '../Label';
+import Author from 'src/components/Author';
+import Date from 'src/components/Date';
+import Label from 'src/components/Label';
 
 import { BugFragment } from './Bug.generated';
+import CommentForm from './CommentForm';
 import TimelineQuery from './TimelineQuery';
 
 const useStyles = makeStyles(theme => ({
   main: {
-    maxWidth: 800,
+    maxWidth: 1000,
     margin: 'auto',
     marginTop: theme.spacing(4),
   },
@@ -39,6 +41,9 @@ const useStyles = makeStyles(theme => ({
     marginTop: theme.spacing(2),
     flex: '0 0 200px',
   },
+  sidebarTitle: {
+    fontWeight: 'bold',
+  },
   labelList: {
     listStyle: 'none',
     padding: 0,
@@ -51,6 +56,12 @@ const useStyles = makeStyles(theme => ({
       display: 'block',
     },
   },
+  noLabel: {
+    ...theme.typography.body2,
+  },
+  commentForm: {
+    marginLeft: 48,
+  },
 }));
 
 type Props = {
@@ -75,10 +86,16 @@ function Bug({ bug }: Props) {
       <div className={classes.container}>
         <div className={classes.timeline}>
           <TimelineQuery id={bug.id} />
+          <div className={classes.commentForm}>
+            <CommentForm bugId={bug.id} />
+          </div>
         </div>
         <div className={classes.sidebar}>
-          <Typography variant={'subtitle1'}>Labels</Typography>
+          <span className={classes.sidebarTitle}>Labels</span>
           <ul className={classes.labelList}>
+            {bug.labels.length === 0 && (
+              <span className={classes.noLabel}>None yet</span>
+            )}
             {bug.labels.map(l => (
               <li className={classes.label} key={l.name}>
                 <Label label={l} key={l.name} />
  
  
  
    
    
  
  
  
    
    @@ -1,7 +1,8 @@
-import CircularProgress from '@material-ui/core/CircularProgress';
 import React from 'react';
 import { RouteComponentProps } from 'react-router-dom';
 
+import CircularProgress from '@material-ui/core/CircularProgress';
+
 import Bug from './Bug';
 import { useGetBugQuery } from './BugQuery.generated';
 
  
  
  
    
    @@ -0,0 +1,5 @@
+mutation AddComment($input: AddCommentInput!) {
+  addComment(input: $input) {
+    operation { id }
+  }
+}
  
  
  
    
    @@ -0,0 +1,146 @@
+import React, { useState, useRef } from 'react';
+
+import Button from '@material-ui/core/Button';
+import Paper from '@material-ui/core/Paper';
+import Tab from '@material-ui/core/Tab';
+import Tabs from '@material-ui/core/Tabs';
+import TextField from '@material-ui/core/TextField';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+
+import Content from 'src/components/Content';
+
+import { useAddCommentMutation } from './CommentForm.generated';
+import { TimelineDocument } from './TimelineQuery.generated';
+
+type StyleProps = { loading: boolean };
+const useStyles = makeStyles<Theme, StyleProps>(theme => ({
+  container: {
+    margin: theme.spacing(2, 0),
+    padding: theme.spacing(0, 2, 2, 2),
+  },
+  textarea: {},
+  tabContent: {
+    margin: theme.spacing(2, 0),
+  },
+  preview: {
+    borderBottom: `solid 3px ${theme.palette.grey['200']}`,
+    minHeight: '5rem',
+  },
+  actions: {
+    display: 'flex',
+    justifyContent: 'flex-end',
+  },
+}));
+
+type TabPanelProps = {
+  children: React.ReactNode;
+  value: number;
+  index: number;
+} & React.HTMLProps<HTMLDivElement>;
+function TabPanel({ children, value, index, ...props }: TabPanelProps) {
+  return (
+    <div
+      role="tabpanel"
+      hidden={value !== index}
+      id={`editor-tabpanel-${index}`}
+      aria-labelledby={`editor-tab-${index}`}
+      {...props}
+    >
+      {value === index && children}
+    </div>
+  );
+}
+
+const a11yProps = (index: number) => ({
+  id: `editor-tab-${index}`,
+  'aria-controls': `editor-tabpanel-${index}`,
+});
+
+type Props = {
+  bugId: string;
+};
+
+function CommentForm({ bugId }: Props) {
+  const [addComment, { loading }] = useAddCommentMutation();
+  const [input, setInput] = useState<string>('');
+  const [tab, setTab] = useState(0);
+  const classes = useStyles({ loading });
+  const form = useRef<HTMLFormElement>(null);
+
+  const submit = () => {
+    addComment({
+      variables: {
+        input: {
+          prefix: bugId,
+          message: input,
+        },
+      },
+      refetchQueries: [
+        // TODO: update the cache instead of refetching
+        {
+          query: TimelineDocument,
+          variables: {
+            id: bugId,
+            first: 100,
+          },
+        },
+      ],
+      awaitRefetchQueries: true,
+    }).then(() => setInput(''));
+  };
+
+  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    submit();
+  };
+
+  const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {
+    // Submit on cmd/ctrl+enter
+    if ((e.metaKey || e.altKey) && e.keyCode === 13) {
+      submit();
+    }
+  };
+
+  return (
+    <Paper className={classes.container}>
+      <form onSubmit={handleSubmit} ref={form}>
+        <Tabs value={tab} onChange={(_, t) => setTab(t)}>
+          <Tab label="Write" {...a11yProps(0)} />
+          <Tab label="Preview" {...a11yProps(1)} />
+        </Tabs>
+        <div className={classes.tabContent}>
+          <TabPanel value={tab} index={0}>
+            <TextField
+              onKeyDown={handleKeyDown}
+              fullWidth
+              label="Comment"
+              placeholder="Leave a comment"
+              className={classes.textarea}
+              multiline
+              value={input}
+              variant="filled"
+              rows="4" // TODO: rowsMin support
+              onChange={(e: any) => setInput(e.target.value)}
+              disabled={loading}
+            />
+          </TabPanel>
+          <TabPanel value={tab} index={1} className={classes.preview}>
+            <Content markdown={input} />
+          </TabPanel>
+        </div>
+        <div className={classes.actions}>
+          <Button
+            variant="contained"
+            color="primary"
+            type="submit"
+            disabled={loading}
+          >
+            Comment
+          </Button>
+        </div>
+      </form>
+    </Paper>
+  );
+}
+
+export default CommentForm;
  
  
  
    
    @@ -1,15 +1,16 @@
-import { makeStyles } from '@material-ui/core/styles';
 import React from 'react';
 
-import Author from '../Author';
-import Date from '../Date';
-import Label from '../Label';
+import { makeStyles } from '@material-ui/core/styles';
+
+import Author from 'src/components/Author';
+import Date from 'src/components/Date';
+import Label from 'src/components/Label';
 
 import { LabelChangeFragment } from './LabelChangeFragment.generated';
 
 const useStyles = makeStyles(theme => ({
   main: {
-    ...theme.typography.body1,
+    ...theme.typography.body2,
     marginLeft: theme.spacing(1) + 40,
   },
   author: {
  
  
  
    
    @@ -1,5 +1,4 @@
-#import "../Author.graphql"
-#import "../Label.graphql"
+#import "../../components/fragments.graphql"
 
 fragment LabelChange on LabelChangeTimelineItem {
   date
  
  
  
    
    @@ -1,11 +1,11 @@
+import React from 'react';
+
 import Paper from '@material-ui/core/Paper';
 import { makeStyles } from '@material-ui/core/styles';
-import React from 'react';
 
-import Author from '../Author';
-import { Avatar } from '../Author';
-import Content from '../Content';
-import Date from '../Date';
+import Author, { Avatar } from 'src/components/Author';
+import Content from 'src/components/Content';
+import Date from 'src/components/Date';
 
 import { AddCommentFragment } from './MessageCommentFragment.generated';
 import { CreateFragment } from './MessageCreateFragment.generated';
@@ -31,6 +31,7 @@ const useStyles = makeStyles(theme => ({
     padding: '0.5rem 1rem',
     borderBottom: '1px solid #ddd',
     display: 'flex',
+    backgroundColor: '#e2f1ff',
   },
   title: {
     flex: 1,
  
  
  
    
    @@ -1,4 +1,4 @@
-#import "../Author.graphql"
+#import "../../components/fragments.graphql"
 
 fragment AddComment on AddCommentTimelineItem {
   createdAt
  
  
  
    
    @@ -1,4 +1,4 @@
-#import "../Author.graphql"
+#import "../../components/fragments.graphql"
 
 fragment Create on CreateTimelineItem {
   createdAt
  
  
  
    
    @@ -1,16 +1,21 @@
-import { makeStyles } from '@material-ui/core/styles';
 import React from 'react';
 
-import Author from '../Author';
-import Date from '../Date';
+import { makeStyles } from '@material-ui/core/styles';
+
+import { Status } from '../../gqlTypes';
+import Author from 'src/components/Author';
+import Date from 'src/components/Date';
 
 import { SetStatusFragment } from './SetStatusFragment.generated';
 
 const useStyles = makeStyles(theme => ({
   main: {
-    ...theme.typography.body1,
+    ...theme.typography.body2,
     marginLeft: theme.spacing(1) + 40,
   },
+  author: {
+    fontWeight: 'bold',
+  },
 }));
 
 type Props = {
@@ -19,10 +24,14 @@ type Props = {
 
 function SetStatus({ op }: Props) {
   const classes = useStyles();
+  const status = { [Status.Open]: 'reopened', [Status.Closed]: 'closed' }[
+    op.status
+  ];
+
   return (
     <div className={classes.main}>
-      <Author author={op.author} bold />
-      <span> {op.status.toLowerCase()} this</span>
+      <Author author={op.author} className={classes.author} />
+      <span> {status} this </span>
       <Date date={op.date} />
     </div>
   );
  
  
  
    
    @@ -1,4 +1,4 @@
-#import "../Author.graphql"
+#import "../../components/fragments.graphql"
 
 fragment SetStatus on SetStatusTimelineItem {
   date
  
  
  
    
    @@ -1,17 +1,25 @@
-import { makeStyles } from '@material-ui/core/styles';
 import React from 'react';
 
-import Author from '../Author';
-import Date from '../Date';
+import { makeStyles } from '@material-ui/core/styles';
+
+import Author from 'src/components/Author';
+import Date from 'src/components/Date';
 
 import { SetTitleFragment } from './SetTitleFragment.generated';
 
 const useStyles = makeStyles(theme => ({
   main: {
-    ...theme.typography.body1,
+    ...theme.typography.body2,
     marginLeft: theme.spacing(1) + 40,
   },
-  bold: {
+  author: {
+    fontWeight: 'bold',
+  },
+  before: {
+    fontWeight: 'bold',
+    textDecoration: 'line-through',
+  },
+  after: {
     fontWeight: 'bold',
   },
 }));
@@ -24,11 +32,11 @@ function SetTitle({ op }: Props) {
   const classes = useStyles();
   return (
     <div className={classes.main}>
-      <Author author={op.author} className={classes.bold} />
+      <Author author={op.author} className={classes.author} />
       <span> changed the title from </span>
-      <span className={classes.bold}>{op.was}</span>
+      <span className={classes.before}>{op.was}</span>
       <span> to </span>
-      <span className={classes.bold}>{op.title}</span>
+      <span className={classes.after}>{op.title}</span> 
       <Date date={op.date} />
     </div>
   );
  
  
  
    
    @@ -1,4 +1,4 @@
-#import "../Author.graphql"
+#import "../../components/fragments.graphql"
 
 fragment SetTitle on SetTitleTimelineItem {
   date
  
  
  
    
    @@ -1,6 +1,7 @@
-import { makeStyles } from '@material-ui/core/styles';
 import React from 'react';
 
+import { makeStyles } from '@material-ui/core/styles';
+
 import LabelChange from './LabelChange';
 import Message from './Message';
 import SetStatus from './SetStatus';
  
  
  
    
    
  
  
  
    
    @@ -1,6 +1,7 @@
-import CircularProgress from '@material-ui/core/CircularProgress';
 import React from 'react';
 
+import CircularProgress from '@material-ui/core/CircularProgress';
+
 import Timeline from './Timeline';
 import { useTimelineQuery } from './TimelineQuery.generated';
 
  
  
  
    
    @@ -0,0 +1 @@
+export { default } from './BugQuery';
  
  
  
    
    @@ -1,5 +1,4 @@
-#import "../Author.graphql"
-#import "../Label.graphql"
+#import "../../components/fragments.graphql"
 
 fragment BugRow on Bug {
   id
  
  
  
    
    @@ -1,15 +1,16 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+
 import TableCell from '@material-ui/core/TableCell/TableCell';
 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 ErrorOutline from '@material-ui/icons/ErrorOutline';
-import React from 'react';
-import { Link } from 'react-router-dom';
 
-import Date from '../Date';
-import Label from '../Label';
-import { Status } from '../gqlTypes';
+import Date from 'src/components/Date';
+import Label from 'src/components/Label';
+import { Status } from 'src/gqlTypes';
 
 import { BugRowFragment } from './BugRow.generated';
 
@@ -99,9 +100,9 @@ function BugRow({ bug }: Props) {
             </div>
           </Link>
           <div className={classes.details}>
-            {bug.humanId} opened
+            {bug.humanId} opened 
             <Date date={bug.createdAt} />
-            by {bug.author.displayName}
+             by {bug.author.displayName}
           </div>
         </div>
       </TableCell>
  
  
  
    
    @@ -1,12 +1,13 @@
+import clsx from 'clsx';
+import { LocationDescriptor } from 'history';
+import React, { useState, useRef } from 'react';
+import { Link } from 'react-router-dom';
+
 import Menu from '@material-ui/core/Menu';
 import MenuItem from '@material-ui/core/MenuItem';
 import { SvgIconProps } from '@material-ui/core/SvgIcon';
 import { makeStyles } from '@material-ui/core/styles';
 import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
-import clsx from 'clsx';
-import { LocationDescriptor } from 'history';
-import React, { useState, useRef } from 'react';
-import { Link } from 'react-router-dom';
 
 export type Query = { [key: string]: Array<string> };
 
@@ -153,7 +154,7 @@ function FilterDropdown({
 
 export type FilterProps = {
   active: boolean;
-  to: LocationDescriptor;
+  to: LocationDescriptor; // the target on click
   icon?: React.ComponentType<SvgIconProps>;
   children: React.ReactNode;
 };
  
  
  
    
    
  
  
  
    
    @@ -1,10 +1,11 @@
 import { pipe } from '@arrows/composition';
+import { LocationDescriptor } from 'history';
+import React from 'react';
+
 import Toolbar from '@material-ui/core/Toolbar';
 import { makeStyles } from '@material-ui/core/styles';
 import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
 import ErrorOutline from '@material-ui/icons/ErrorOutline';
-import { LocationDescriptor } from 'history';
-import React from 'react';
 
 import {
   FilterDropdown,
@@ -31,7 +32,7 @@ const useStyles = makeStyles(theme => ({
 
 // This prepends the filter text with a count
 type CountingFilterProps = {
-  query: string;
+  query: string; // the query used as a source to count the number of element
   children: React.ReactNode;
 } & FilterProps;
 function CountingFilter({ query, children, ...props }: CountingFilterProps) {
@@ -71,6 +72,12 @@ function FilterToolbar({ query, queryLocation }: Props) {
     ...params,
     [key]: [value],
   });
+  const toggleParam = (key: string, value: string) => (
+    params: Query
+  ): Query => ({
+    ...params,
+    [key]: params[key] && params[key].includes(value) ? [] : [value],
+  });
   const clearParam = (key: string) => (params: Query): Query => ({
     ...params,
     [key]: [],
@@ -86,7 +93,7 @@ function FilterToolbar({ query, queryLocation }: Props) {
           clearParam('sort'),
           stringify
         )(params)}
-        to={pipe(replaceParam('status', 'open'), loc)(params)}
+        to={pipe(toggleParam('status', 'open'), loc)(params)}
         icon={ErrorOutline}
       >
         open
@@ -98,7 +105,7 @@ function FilterToolbar({ query, queryLocation }: Props) {
           clearParam('sort'),
           stringify
         )(params)}
-        to={pipe(replaceParam('status', 'closed'), loc)(params)}
+        to={pipe(toggleParam('status', 'closed'), loc)(params)}
         icon={CheckCircleOutline}
       >
         closed
  
  
  
    
    @@ -1,6 +1,7 @@
+import React from 'react';
+
 import Table from '@material-ui/core/Table/Table';
 import TableBody from '@material-ui/core/TableBody/TableBody';
-import React from 'react';
 
 import BugRow from './BugRow';
 import { BugListFragment } from './ListQuery.generated';
  
  
  
    
    
  
  
  
    
    @@ -1,3 +1,7 @@
+import { ApolloError } from 'apollo-boost';
+import React, { useState, useEffect, useRef } from 'react';
+import { useLocation, useHistory, Link } from 'react-router-dom';
+
 import IconButton from '@material-ui/core/IconButton';
 import InputBase from '@material-ui/core/InputBase';
 import Paper from '@material-ui/core/Paper';
@@ -6,9 +10,6 @@ import ErrorOutline from '@material-ui/icons/ErrorOutline';
 import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
 import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
 import Skeleton from '@material-ui/lab/Skeleton';
-import { ApolloError } from 'apollo-boost';
-import React, { useState, useEffect, useRef } from 'react';
-import { useLocation, useHistory, Link } from 'react-router-dom';
 
 import FilterToolbar from './FilterToolbar';
 import List from './List';
@@ -163,7 +164,7 @@ function ListQuery() {
   const location = useLocation();
   const history = useHistory();
   const params = new URLSearchParams(location.search);
-  const query = params.get('q') || '';
+  const query = params.has('q') ? params.get('q') || '' : 'status:open';
 
   const [input, setInput] = useState(query);
 
  
  
  
    
    @@ -0,0 +1 @@
+export { default } from './ListQuery';
  
  
  
    
    @@ -0,0 +1,11 @@
+import { createMuiTheme } from '@material-ui/core/styles';
+
+const theme = createMuiTheme({
+  palette: {
+    primary: {
+      main: '#263238',
+    },
+  },
+});
+
+export default theme;
  
  
  
    
    @@ -1,7 +1,11 @@
 {
   "compilerOptions": {
     "target": "es5",
-    "lib": ["dom", "dom.iterable", "esnext"],
+    "lib": [
+      "dom",
+      "dom.iterable",
+      "esnext"
+    ],
     "allowJs": true,
     "skipLibCheck": true,
     "esModuleInterop": true,
@@ -14,7 +18,13 @@
     "isolatedModules": true,
     "noEmit": true,
     "jsx": "react",
-    "typeRoots": ["node_modules/@types/", "types/"]
+    "typeRoots": [
+      "node_modules/@types/",
+      "types/"
+    ],
+    "baseUrl": "."
   },
-  "include": ["src"]
+  "include": [
+    "src"
+  ]
 }