webui: Split into multiple, smaller components

Quentin Gliech created

Change summary

webui/src/App.js        |   4 
webui/src/Bug.js        | 101 +++++++-----------------------------------
webui/src/BugPage.js    |  29 ++++++++++++
webui/src/BugSummary.js |  51 +++++++++++++++++++++
webui/src/Comment.js    |  44 ++++++++++++++++++
5 files changed, 143 insertions(+), 86 deletions(-)

Detailed changes

webui/src/App.js 🔗

@@ -6,7 +6,7 @@ import CssBaseline from "@material-ui/core/CssBaseline";
 import Toolbar from "@material-ui/core/Toolbar";
 import Typography from "@material-ui/core/Typography";
 
-import Bug from "./Bug";
+import BugPage from "./BugPage";
 
 const Home = () => <h1>Home</h1>;
 
@@ -22,7 +22,7 @@ const App = ({ location }) => (
     </AppBar>
     <Switch>
       <Route path="/" exact component={Home} />
-      <Route path="/bug/:id" exact component={Bug} />
+      <Route path="/bug/:id" exact component={BugPage} />
     </Switch>
   </React.Fragment>
 );

webui/src/Bug.js 🔗

@@ -1,105 +1,38 @@
 import React from "react";
-import { Query } from "react-apollo";
 import gql from "graphql-tag";
 import { withStyles } from "@material-ui/core/styles";
 
-import Avatar from "@material-ui/core/Avatar";
-import Card from "@material-ui/core/Card";
-import CardContent from "@material-ui/core/CardContent";
-import CardHeader from "@material-ui/core/CardHeader";
-import Chip from "@material-ui/core/Chip";
-import CircularProgress from "@material-ui/core/CircularProgress";
-import Typography from "@material-ui/core/Typography";
+import Comment from "./Comment";
+import BugSummary from "./BugSummary";
 
 const styles = theme => ({
   main: {
     maxWidth: 600,
     margin: "auto",
     marginTop: theme.spacing.unit * 4
-  },
-  labelList: {
-    display: "flex",
-    flexWrap: "wrap",
-    marginTop: theme.spacing.unit
-  },
-  label: {
-    marginRight: theme.spacing.unit
-  },
-  summary: {
-    marginBottom: theme.spacing.unit * 2
-  },
-  comment: {
-    marginBottom: theme.spacing.unit
   }
 });
 
-const QUERY = gql`
-  query GetBug($id: BugID!) {
-    bug(id: $id) {
-      id
-      title
-      status
-      labels
-      comments {
-        message
-        author {
-          name
-          email
-        }
-      }
-    }
-  }
-`;
-
-const Comment = withStyles(styles)(({ comment, classes }) => (
-  <Card className={classes.comment}>
-    <CardHeader
-      avatar={
-        <Avatar aria-label={comment.author.name}>
-          {comment.author.name[0].toUpperCase()}
-        </Avatar>
-      }
-      title={comment.author.name}
-      subheader={comment.author.email}
-    />
-    <CardContent>
-      <Typography component="p">{comment.message}</Typography>
-    </CardContent>
-  </Card>
-));
-
-const BugView = withStyles(styles)(({ bug, classes }) => (
+const Bug = ({ bug, classes }) => (
   <main className={classes.main}>
-    <Card className={classes.summary}>
-      <CardContent>
-        <Typography variant="headline" component="h2">
-          {bug.title}
-        </Typography>
-        <Typography variant="subheading" component="h3" title={bug.id}>
-          #{bug.id.slice(0, 8)} • {bug.status.toUpperCase()}
-        </Typography>
-        <div className={classes.labelList}>
-          {bug.labels.map(label => (
-            <Chip key={label} label={label} className={classes.label} />
-          ))}
-        </div>
-      </CardContent>
-    </Card>
+    <BugSummary bug={bug} />
 
     {bug.comments.map((comment, index) => (
       <Comment key={index} comment={comment} />
     ))}
   </main>
-));
-
-const Bug = ({ match }) => (
-  <Query query={QUERY} variables={{ id: match.params.id }}>
-    {({ loading, error, data }) => {
-      if (loading) return <CircularProgress />;
-      if (error) return <p>Error.</p>;
-      return <BugView bug={data.bug} />;
-    }}
-  </Query>
 );
 
-export default Bug;
+Bug.fragment = gql`
+  fragment Bug on Bug {
+    ...BugSummary
+    comments {
+      ...Comment
+    }
+  }
+
+  ${BugSummary.fragment}
+  ${Comment.fragment}
+`;
+
+export default withStyles(styles)(Bug);

webui/src/BugPage.js 🔗

@@ -0,0 +1,29 @@
+import React from "react";
+import { Query } from "react-apollo";
+import gql from "graphql-tag";
+
+import CircularProgress from "@material-ui/core/CircularProgress";
+
+import Bug from "./Bug";
+
+const QUERY = gql`
+  query GetBug($id: BugID!) {
+    bug(id: $id) {
+      ...Bug
+    }
+  }
+
+  ${Bug.fragment}
+`;
+
+const BugPage = ({ match }) => (
+  <Query query={QUERY} variables={{ id: match.params.id }}>
+    {({ loading, error, data }) => {
+      if (loading) return <CircularProgress />;
+      if (error) return <p>Error.</p>;
+      return <Bug bug={data.bug} />;
+    }}
+  </Query>
+);
+
+export default BugPage;

webui/src/BugSummary.js 🔗

@@ -0,0 +1,51 @@
+import React from "react";
+import gql from "graphql-tag";
+import { withStyles } from "@material-ui/core/styles";
+
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import Chip from "@material-ui/core/Chip";
+import Typography from "@material-ui/core/Typography";
+
+const styles = theme => ({
+  labelList: {
+    display: "flex",
+    flexWrap: "wrap",
+    marginTop: theme.spacing.unit
+  },
+  label: {
+    marginRight: theme.spacing.unit
+  },
+  summary: {
+    marginBottom: theme.spacing.unit * 2
+  }
+});
+
+const BugSummary = ({ bug, classes }) => (
+  <Card className={classes.summary}>
+    <CardContent>
+      <Typography variant="headline" component="h2">
+        {bug.title}
+      </Typography>
+      <Typography variant="subheading" component="h3" title={bug.id}>
+        #{bug.id.slice(0, 8)} • {bug.status.toUpperCase()}
+      </Typography>
+      <div className={classes.labelList}>
+        {bug.labels.map(label => (
+          <Chip key={label} label={label} className={classes.label} />
+        ))}
+      </div>
+    </CardContent>
+  </Card>
+);
+
+BugSummary.fragment = gql`
+  fragment BugSummary on Bug {
+    id
+    title
+    status
+    labels
+  }
+`;
+
+export default withStyles(styles)(BugSummary);

webui/src/Comment.js 🔗

@@ -0,0 +1,44 @@
+import React from "react";
+import gql from "graphql-tag";
+import { withStyles } from "@material-ui/core/styles";
+
+import Avatar from "@material-ui/core/Avatar";
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import CardHeader from "@material-ui/core/CardHeader";
+import Typography from "@material-ui/core/Typography";
+
+const styles = theme => ({
+  comment: {
+    marginBottom: theme.spacing.unit
+  }
+});
+
+const Comment = withStyles(styles)(({ comment, classes }) => (
+  <Card className={classes.comment}>
+    <CardHeader
+      avatar={
+        <Avatar aria-label={comment.author.name}>
+          {comment.author.name[0].toUpperCase()}
+        </Avatar>
+      }
+      title={comment.author.name}
+      subheader={comment.author.email}
+    />
+    <CardContent>
+      <Typography component="p">{comment.message}</Typography>
+    </CardContent>
+  </Card>
+));
+
+Comment.fragment = gql`
+  fragment Comment on Comment {
+    message
+    author {
+      name
+      email
+    }
+  }
+`;
+
+export default withStyles(styles)(Comment);