From 29f47225448e5c8a92db051232502a445017e032 Mon Sep 17 00:00:00 2001
From: manisha <manisha_kanyal.scsebtech@galgotiasuniversity.edu.in>
Date: Jul 22 2021 10:53:01 +0000
Subject: changed class based components to functional based


---

diff --git a/src/App.js b/src/App.js
index 2858284..e04e484 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,4 +1,4 @@
-import React, { Component } from "react"
+import React from "react"
 
 import { Route, Switch } from "react-router"
 import { BrowserRouter } from "react-router-dom"
@@ -6,51 +6,49 @@ import { BrowserRouter } from "react-router-dom"
 import Wizard from "./wizard/Wizard"
 import LandingPage from "./landingpage/LandingPage"
 import NotFound from "./NotFound"
-class App extends Component {
-  render() {
-    return (
-      <BrowserRouter basename={window.env.SUBDIR}>
-        <Switch>
-          <Route path="/" exact component={LandingPage} />
-          <Route path="/landingpage" component={LandingPage} />
-          <Route
-            path="/wizard/:duration/:provider/:action/:issues"
-            render={(props) => {
-              return <Wizard step="step5" {...props} />
-            }}
-          />
-          <Route
-            path="/wizard/:duration/:provider/:action"
-            render={(props) => {
-              return <Wizard step="step4" {...props} />
-            }}
-          />
+const App = () => {
+  return (
+    <BrowserRouter basename={window.env.SUBDIR}>
+      <Switch>
+        <Route path="/" exact component={LandingPage} />
+        <Route path="/landingpage" component={LandingPage} />
+        <Route
+          path="/wizard/:duration/:provider/:action/:issues"
+          render={(props) => {
+            return <Wizard step="step5" {...props} />
+          }}
+        />
+        <Route
+          path="/wizard/:duration/:provider/:action"
+          render={(props) => {
+            return <Wizard step="step4" {...props} />
+          }}
+        />
 
-          <Route
-            path="/wizard/:duration/:provider"
-            render={(props) => {
-              return <Wizard step="step3" {...props} />
-            }}
-          />
+        <Route
+          path="/wizard/:duration/:provider"
+          render={(props) => {
+            return <Wizard step="step3" {...props} />
+          }}
+        />
 
-          <Route
-            path="/wizard/:duration"
-            render={(props) => {
-              return <Wizard step="step2" {...props} />
-            }}
-          />
+        <Route
+          path="/wizard/:duration"
+          render={(props) => {
+            return <Wizard step="step2" {...props} />
+          }}
+        />
 
-          <Route
-            path="/wizard"
-            render={(props) => {
-              return <Wizard step="step1" {...props} />
-            }}
-          />
-          <Route component={NotFound} />
-        </Switch>
-      </BrowserRouter>
-    )
-  }
+        <Route
+          path="/wizard"
+          render={(props) => {
+            return <Wizard step="step1" {...props} />
+          }}
+        />
+        <Route component={NotFound} />
+      </Switch>
+    </BrowserRouter>
+  )
 }
 
 export default App
diff --git a/src/NotFound.js b/src/NotFound.js
index 7ff839c..9790a44 100644
--- a/src/NotFound.js
+++ b/src/NotFound.js
@@ -1,28 +1,24 @@
-import React, { Component } from "react"
+import React from "react"
 import Layout from "./layout/Layout"
 import { Link } from "react-router-dom"
 import { Container } from "reactstrap"
 
-class Wizard extends Component {
-  render() {
-    return (
-      <Layout>
-        <Container>
-          <p className="text-md-center">
-            <h2>404</h2>
-            <h3>
-              <span role="img" aria-label="sad">
-                😢
-              </span>
-            </h3>
-            <Link to="/">
-              Go to home page
-            </Link>
-          </p>
-        </Container>
-      </Layout>
-    )
-  }
+const Wizard = () => {
+  return (
+    <Layout>
+      <Container>
+        <p className="text-md-center">
+          <h2>404</h2>
+          <h3>
+            <span role="img" aria-label="sad">
+              😢
+            </span>
+          </h3>
+          <Link to="/">Go to home page</Link>
+        </p>
+      </Container>
+    </Layout>
+  )
 }
 
 export default Wizard
diff --git a/src/landingpage/Blockers.js b/src/landingpage/Blockers.js
index 22e1a9a..95e71bf 100644
--- a/src/landingpage/Blockers.js
+++ b/src/landingpage/Blockers.js
@@ -1,32 +1,25 @@
-import React, { Component } from "react"
+import React from "react"
 import { Row, Card, CardBody } from "reactstrap"
 import SourceLink from "./SourceLink"
 import BugStats from "./common/BugStats"
 
-class Blockers extends Component {
-  constructor(props) {
-    super(props)
-    this.state = { blockerbugs: {}, release: 0 }
-  }
-
-  render() {
-    if (this.props.data)
-      return (
-        <Card className="cards">
-          <CardBody>
-            <h1 className="text-center padded">
-              Fedora {this.props.release} blockers and FEs{" "}
-              <SourceLink href="https://qa.fedoraproject.org/blockerbugs/" />
-            </h1>
-            <Row>
-              <BugStats milestone={"Beta"} stats={this.props.data.beta} />
-
-              <BugStats milestone={"Final"} stats={this.props.data.final} />
-            </Row>
-          </CardBody>
-        </Card>
-      )
-  }
+const Blockers = (props) => {
+  return (
+    props.data && (
+      <Card className="cards">
+        <CardBody>
+          <h1 className="text-center padded">
+            Fedora {props.release} blockers and FEs{" "}
+            <SourceLink href="https://qa.fedoraproject.org/blockerbugs/" />
+          </h1>
+          <Row>
+            <BugStats milestone={"Beta"} stats={props.data.beta} />
+            <BugStats milestone={"Final"} stats={props.data.final} />
+          </Row>
+        </CardBody>
+      </Card>
+    )
+  )
 }
 
 export default Blockers
diff --git a/src/landingpage/Events.js b/src/landingpage/Events.js
index 811f07e..0c5d3c1 100644
--- a/src/landingpage/Events.js
+++ b/src/landingpage/Events.js
@@ -1,77 +1,64 @@
-import React, { Component } from "react"
+import React from "react"
 import dateFormat from "dateformat"
 import SourceLink from "./SourceLink"
 import { Card, CardBody, Row, Col } from "reactstrap"
 
-class Events extends Component {
-  constructor(props) {
-    super(props)
-    this.state = { meetings: [] }
-  }
-
-  render() {
-    const meetings = this.props.data.map((meeting) => {
-      const old = new Date(meeting.start)
-      var date = old.getDate()
-      var month = old.toLocaleString("default", { month: "short" })
-      var time = dateFormat(new Date(old.getTime() - old.getTimezoneOffset() * 60000), "HH:MM")
-      if (time.fullday) {
-        time = date.slice(0, -5) + "All day"
-      }
-      return (
-        <Event
-          key={meeting.link}
-          date={date}
-          month={month}
-          time={time}
-          summary={meeting.summary}
-          link={meeting.link}
-          info={meeting.info}
-        />
-      )
-    })
+const Events = (props) => {
+  const meetings = props.data.map((meeting) => {
+    const old = new Date(meeting.start)
+    var date = old.getDate()
+    var month = old.toLocaleString("default", { month: "short" })
+    var time = dateFormat(new Date(old.getTime() - old.getTimezoneOffset() * 60000), "HH:MM")
+    if (time.fullday) {
+      time = date.slice(0, -5) + "All day"
+    }
     return (
-      <Card className="cards">
-        <CardBody>
-          <h1 className="text-center padded">
-            Meetings and testdays in the next 7 days{" "}
-            <SourceLink href="https://apps.fedoraproject.org/calendar/QA/" />
-          </h1>
-          <div className="col-md-12 padded">{meetings}</div>
-        </CardBody>
-      </Card>
+      <Event
+        key={meeting.link}
+        date={date}
+        month={month}
+        time={time}
+        summary={meeting.summary}
+        link={meeting.link}
+        info={meeting.info}
+      />
     )
-  }
+  })
+  return (
+    <Card className="cards">
+      <CardBody>
+        <h1 className="text-center padded">
+          Meetings and testdays in the next 7 days{" "}
+          <SourceLink href="https://apps.fedoraproject.org/calendar/QA/" />
+        </h1>
+        <div className="col-md-12 padded">{meetings}</div>
+      </CardBody>
+    </Card>
+  )
 }
 
-class Event extends Component {
-  render() {
-    return (
-      <Row>
-        <Col md={6}>
-          <div className="d-flex flex-row align-items-center event">
-            <div className="d-flex flex-column align-items-center date">
-              <span className="month"> {this.props.month}</span>
-              <span className="day">{this.props.date}</span>
-            </div>
+const Event = (props) => {
+  return (
+    <Row>
+      <Col md={6}>
+        <div className="d-flex flex-row align-items-center event">
+          <div className="d-flex flex-column align-items-center date">
+            <span className="month"> {props.month}</span>
+            <span className="day">{props.date}</span>
+          </div>
 
-            <div className="d-flex flex-column align-items-left">
-              <span className="title">
-                <a
-                  className="events"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  href={this.props.link}>
-                  {this.props.summary}
-                </a>
-              </span>
-              <span className="time">{this.props.time}</span>
-            </div>
+          <div className="d-flex flex-column align-items-left">
+            <span className="title">
+              <a className="events" target="_blank" rel="noopener noreferrer" href={props.link}>
+                {props.summary}
+              </a>
+            </span>
+            <span className="time">{props.time}</span>
           </div>
-        </Col>
-      </Row>
-    )
-  }
+        </div>
+      </Col>
+    </Row>
+  )
 }
 
 export default Events
diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js
index 76f261f..f95ebed 100644
--- a/src/landingpage/LandingPage.js
+++ b/src/landingpage/LandingPage.js
@@ -1,4 +1,4 @@
-import React, { Component } from "react"
+import React, { useEffect, useState } from "react"
 import {
   Container,
   Row,
@@ -16,94 +16,93 @@ import Events from "./Events"
 import Blockers from "./Blockers"
 import Minutes from "./Minutes"
 import * as R from "ramda"
-import { connect } from "react-redux"
+import { shallowEqual, useDispatch, useSelector } from "react-redux"
 import { loadData } from "../actions/reduxActions"
 import Cookies from "universal-cookie"
 
-class LandingPage extends Component {
-  constructor(props) {
-    super(props)
-    this.cookies = new Cookies()
-    this.available_components = ["events", "blockers", "minutes"]
-    let enabled_components = this.cookies.get("landingpage_enabled_components")
-    if (enabled_components === undefined) {
-      enabled_components = [...this.available_components]
-      this.cookies.set("landingpage_enabled_components", enabled_components, {
-        path: "/",
-      })
-    }
-    this.state = {
-      blockerbugs: {},
-      devel: 0,
-      meetings: [],
-      schedule: [],
-      last_qa_meeting: {},
-      stable: 0,
-      config_mode: false,
-      enabled_components: enabled_components,
-      showModal: false,
-    }
-    this.toggleModal = this.toggleModal.bind(this)
-    this.handleVisibilityChange = this.handleVisibilityChange.bind(this)
-  }
-  componentDidMount() {
-    this.props.dispatch(loadData())
+const LandingPage = () => {
+  const cookies = new Cookies()
+  let available_components = ["events", "blockers", "minutes"]
+  let enabled_components = cookies.get("landingpage_enabled_components")
+  if (enabled_components === undefined) {
+    enabled_components = [...available_components]
+    cookies.set("landingpage_enabled_components", enabled_components, {
+      path: "/",
+    })
   }
 
-  handleVisibilityChange(e, item) {
-    let enabled_components = [...this.state.enabled_components]
+  const [state, setState] = useState({
+    blockerbugs: {},
+    devel: 0,
+    meetings: [],
+    schedule: [],
+    last_qa_meeting: {},
+    stable: 0,
+    config_mode: false,
+    enabled_components: enabled_components,
+    showModal: false,
+  })
+
+  const selectAction = (state) => state.landing_page.api_call_status
+  const api_call_status = useSelector(selectAction, shallowEqual)
+  const dispatch = useDispatch()
+
+  const landingPageData = useSelector((state) => state.landing_page)
+
+  useEffect(() => {
+    dispatch(loadData())
+  }, [dispatch])
+
+  const handleVisibilityChange = (e, item) => {
+    let enabled_components = [...state.enabled_components]
     if (enabled_components.includes(item)) {
       enabled_components.splice(enabled_components.indexOf(item), 1)
     } else {
       enabled_components.push(item)
-      enabled_components = this.available_components.filter((c) => enabled_components.includes(c))
+      enabled_components = available_components.filter((c) => enabled_components.includes(c))
     }
-    this.cookies.set("landingpage_enabled_components", enabled_components, {
+    cookies.set("landingpage_enabled_components", enabled_components, {
       path: "/",
     })
-    this.setState({ enabled_components: enabled_components })
-  }
-
-  toggle_config_mode(e) {
-    let config_mode = !this.state.config_mode
-    this.setState({ config_mode: config_mode })
-    e.preventDefault()
+    setState({ ...state, enabled_components: enabled_components })
   }
 
-  toggleModal() {
-    let modalState = !this.state.showModal
-    this.setState({
+  const toggleModal = () => {
+    let modalState = !state.showModal
+    setState({
+      ...state,
       showModal: modalState,
     })
   }
-  render() {
-    const available_components = {
-      events: <Events data={this.props.meetings} />,
-      blockers: <Blockers data={this.props.blockerbugs} release={this.props.devel} />,
-      minutes: <Minutes data={this.props.last_qa_meeting} />,
-    }
-    let components = R.splitEvery(
-      2,
-      this.state.config_mode ? this.available_components : this.state.enabled_components
-    )
-    components = components.map((row) => (
-      <React.Fragment key={row}>
-        {row.map((item) => (
-          <div className="padded col-md-6" key={item}>
-            {available_components[item]}
-          </div>
-        ))}
-      </React.Fragment>
-    ))
 
-    return (
-      <Layout apiCallStatus={this.props.api_call_status}>
+  const available_components_mapper = {
+    events: <Events data={landingPageData.meetings} />,
+    blockers: <Blockers data={landingPageData.blockerbugs} release={state.devel} />,
+    minutes: <Minutes data={landingPageData.last_qa_meeting} />,
+  }
+  let components = R.splitEvery(
+    2,
+    state.config_mode ? available_components : state.enabled_components
+  )
+  components = components.map((row) => (
+    <React.Fragment key={row}>
+      {row.map((item) => (
+        <div className="padded col-md-6" key={item}>
+          {available_components_mapper[item]}
+        </div>
+      ))}
+    </React.Fragment>
+  ))
+
+  return (
+    <>
+      <Layout apiCallStatus={api_call_status}>
         <div>
           <div className="bluebox">
             <Container>
               <Row>
                 <div className="col-md-12">
-                  <Timeline data={this.props.schedule} />
+                  <Timeline data={landingPageData.schedule} />
                 </div>
               </Row>
             </Container>
@@ -112,13 +111,13 @@ class LandingPage extends Component {
             <Row>
               {components}
               <div className="padded col-md-12 text-right col-md-offset-2">
-                <Button className="mt" color="primary" onClick={this.toggleModal}>
+                <Button className="mt" color="primary" onClick={toggleModal}>
                   <i className="fas fa-cog"></i>
                 </Button>
-                <Modal isOpen={this.state.showModal} toggle={this.toggleModal}>
+                <Modal isOpen={state.showModal} toggle={toggleModal}>
                   <ModalHeader>Visibility Configuration</ModalHeader>
                   <ModalBody>
-                    {this.available_components.map((item) => (
+                    {available_components.map((item) => (
                       <React.Fragment key={item}>
                         <Col sm="12">
                           <div className="custom-control custom-switch">
@@ -126,8 +125,8 @@ class LandingPage extends Component {
                               type="checkbox"
                               className="custom-control-input"
                               id={item}
-                              checked={this.state.enabled_components.includes(item)}
-                              onChange={(e) => this.handleVisibilityChange(e, item)}
+                              checked={state.enabled_components.includes(item)}
+                              onChange={(e) => handleVisibilityChange(e, item)}
                             />{" "}
                             <label className="custom-control-label" htmlFor={item}>
                               {item === "events"
@@ -142,7 +141,7 @@ class LandingPage extends Component {
                     ))}
                   </ModalBody>
                   <ModalFooter>
-                    <Button color="primary" onClick={this.toggleModal}>
+                    <Button color="primary" onClick={toggleModal}>
                       Close
                     </Button>
                   </ModalFooter>
@@ -167,14 +166,8 @@ class LandingPage extends Component {
           </Container>
         </div>
       </Layout>
-    )
-  }
-}
-
-const mapStateToProps = (state) => {
-  return {
-    ...state.landing_page,
-  }
+    </>
+  )
 }
 
-export default connect(mapStateToProps)(LandingPage)
+export default LandingPage
diff --git a/src/landingpage/Minutes.js b/src/landingpage/Minutes.js
index 7f82197..297ba37 100644
--- a/src/landingpage/Minutes.js
+++ b/src/landingpage/Minutes.js
@@ -1,31 +1,29 @@
-import React, { Component } from "react"
+import React from "react"
 import { Card, CardBody } from "reactstrap"
 
-class Events extends Component {
-  render() {
-    return (
-      <Card className="cards">
-        <CardBody>
-          <h1 className="text-center padded">Fedora QA Meeting Minutes</h1>
-          <div className="events">
-            <a target="_blank" href={this.props.data.link} rel="noopener noreferrer">
-              Latest minutes from {this.props.data.date}
-            </a>
-            <br />
-            Visit{" "}
-            <a
-              target="_blank"
-              href="https://meetbot.fedoraproject.org/sresults/?group_id=fedora-qa&type=team"
-              rel="noopener noreferrer">
-              meetbot
-            </a>{" "}
-            to see older.
-            <br />
-          </div>
-        </CardBody>
-      </Card>
-    )
-  }
+const Events = (props) => {
+  return (
+    <Card className="cards">
+      <CardBody>
+        <h1 className="text-center padded">Fedora QA Meeting Minutes</h1>
+        <div className="events">
+          <a target="_blank" href={props.data.link} rel="noopener noreferrer">
+            Latest minutes from {props.data.date}
+          </a>
+          <br />
+          Visit{" "}
+          <a
+            target="_blank"
+            href="https://meetbot.fedoraproject.org/sresults/?group_id=fedora-qa&type=team"
+            rel="noopener noreferrer">
+            meetbot
+          </a>{" "}
+          to see older.
+          <br />
+        </div>
+      </CardBody>
+    </Card>
+  )
 }
 
 export default Events
diff --git a/src/landingpage/SourceLink.js b/src/landingpage/SourceLink.js
index 76cfa0b..ce2909e 100644
--- a/src/landingpage/SourceLink.js
+++ b/src/landingpage/SourceLink.js
@@ -1,17 +1,11 @@
-import React, {Component} from 'react'
+import React from "react"
 
-class SourceLink extends Component {
-    render() {
-        return (
-            <a
-                target="_blank"
-                rel="noopener noreferrer"
-                href={this.props.href}
-                className="smallsuper">
-                <i className="fas fa-external-link-alt"></i>
-            </a>
-        )
-    }
+const SourceLink = (props) => {
+  return (
+    <a target="_blank" rel="noopener noreferrer" href={props.href} className="smallsuper">
+      <i className="fas fa-external-link-alt"></i>
+    </a>
+  )
 }
 
 export default SourceLink
diff --git a/src/landingpage/Timeline.js b/src/landingpage/Timeline.js
index c49caff..b68bc2b 100644
--- a/src/landingpage/Timeline.js
+++ b/src/landingpage/Timeline.js
@@ -1,14 +1,9 @@
-import React, { Component } from "react"
+import React from "react"
 import { Card, CardBody } from "reactstrap"
 import SourceLink from "./SourceLink"
 
-class Timeline extends Component {
-  constructor(props) {
-    super(props)
-    this.state = { schedule: [] }
-  }
-
-  get_title(summary) {
+const Timeline = (props) => {
+  const get_title = (summary) => {
     summary = summary.toLowerCase()
     if (summary.includes("freeze"))
       return "At the milestone freeze, pushes from the updates-testing to the stable repository are suspended until the release candidate is accepted."
@@ -20,71 +15,64 @@ class Timeline extends Component {
       return "Release candidate was accepted (violating no milestone criteria) and was released."
   }
 
-  render() {
-    const line = this.props.data.map((milestone) => {
-      return (
-        <td key={"line" + milestone.summary}>
-          <Line color={milestone.current ? "#2371ae" : "#dcdcdc"} />
-        </td>
-      )
-    })
-
-    const dates = this.props.data.map((milestone) => {
-      return (
-        <td key={"dates" + milestone.summary} width="150">
-          <b>{milestone.date}</b>
-        </td>
-      )
-    })
+  const line = props.data.map((milestone) => {
+    return (
+      <td key={"line" + milestone.summary}>
+        <Line color={milestone.current ? "#2371ae" : "#dcdcdc"} />
+      </td>
+    )
+  })
 
-    const schedule = this.props.data.map((milestone) => {
-      return (
-        <td
-          key={"schedule" + milestone.summary}
-          title={this.get_title(milestone.summary)}
-          width="150">
-          {milestone.summary} <i className="fas fa-question-circle light"></i>
-        </td>
-      )
-    })
+  const dates = props.data.map((milestone) => {
     return (
-      <div>
-        <Card>
-          <CardBody>
-            <h1 className="text-center padded">
-              Current development schedule{" "}
-              <SourceLink href="https://fedorapeople.org/groups/schedule/" />
-            </h1>
-            <div className="table-responsive">
-              <table className="timeline">
-                <tbody>
-                  <tr>{line}</tr>
-                  <tr>{dates}</tr>
-                  <tr>{schedule}</tr>
-                </tbody>
-              </table>
-            </div>
-            <h6 className="text-center padded">This is about the development schedule</h6>
-          </CardBody>
-        </Card>
-      </div>
+      <td key={"dates" + milestone.summary} width="150">
+        <b>{milestone.date}</b>
+      </td>
     )
-  }
-}
+  })
 
-class Line extends Component {
-  render() {
-    const lineStyle = {
-      stroke: this.props.color,
-      strokeWidth: "3",
-    }
+  const schedule = props.data.map((milestone) => {
     return (
-      <svg width="150" height="20" version="1.1">
-        <line x1="0" y1="50%" x2="100%" y2="50%" style={lineStyle} />
-        <circle cx="50%" cy="50%" r="4" style={lineStyle} fill="#f8f9fa" />
-      </svg>
+      <td key={"schedule" + milestone.summary} title={get_title(milestone.summary)} width="150">
+        {milestone.summary} <i className="fas fa-question-circle light"></i>
+      </td>
     )
+  })
+  return (
+    <div>
+      <Card>
+        <CardBody>
+          <h1 className="text-center padded">
+            Current development schedule{" "}
+            <SourceLink href="https://fedorapeople.org/groups/schedule/" />
+          </h1>
+          <div className="table-responsive">
+            <table className="timeline">
+              <tbody>
+                <tr>{line}</tr>
+                <tr>{dates}</tr>
+                <tr>{schedule}</tr>
+              </tbody>
+            </table>
+          </div>
+          <h6 className="text-center padded">This is about the development schedule</h6>
+        </CardBody>
+      </Card>
+    </div>
+  )
+}
+
+const Line = (props) => {
+  const lineStyle = {
+    stroke: props.color,
+    strokeWidth: "3",
   }
+  return (
+    <svg width="150" height="20" version="1.1">
+      <line x1="0" y1="50%" x2="100%" y2="50%" style={lineStyle} />
+      <circle cx="50%" cy="50%" r="4" style={lineStyle} fill="#f8f9fa" />
+    </svg>
+  )
 }
 
 export default Timeline
diff --git a/src/landingpage/common/BugStats.js b/src/landingpage/common/BugStats.js
index b3be054..015de59 100644
--- a/src/landingpage/common/BugStats.js
+++ b/src/landingpage/common/BugStats.js
@@ -15,22 +15,26 @@ const BugStats = (props) => {
           </tr>
         </thead>
         <tbody>
-          <tr>
-            <td>Proposed Blockers</td>
-            <td className="bugscount">{stats.blockers_proposed}</td>
-          </tr>
-          <tr>
-            <td>Accepted Blockers</td>
-            <td className="bugscount">{stats.blockers}</td>
-          </tr>
-          <tr>
-            <td>Proposed FEs</td>
-            <td className="bugscount">{stats.fe_proposed}</td>
-          </tr>
-          <tr>
-            <td>Accepted FEs</td>
-            <td className="bugscount">{stats.fe}</td>
-          </tr>
+          {stats && (
+            <>
+              <tr>
+                <td>Proposed Blockers</td>
+                <td className="bugscount">{stats.blockers_proposed}</td>
+              </tr>
+              <tr>
+                <td>Accepted Blockers</td>
+                <td className="bugscount">{stats.blockers}</td>
+              </tr>
+              <tr>
+                <td>Proposed FEs</td>
+                <td className="bugscount">{stats.fe_proposed}</td>
+              </tr>
+              <tr>
+                <td>Accepted FEs</td>
+                <td className="bugscount">{stats.fe}</td>
+              </tr>
+            </>
+          )}
         </tbody>
       </Table>
     </div>
diff --git a/src/layout/Masthead.js b/src/layout/Masthead.js
index 018db74..4fac37c 100644
--- a/src/layout/Masthead.js
+++ b/src/layout/Masthead.js
@@ -57,7 +57,7 @@ const Masthead = () => {
               {api_call_status() === API_CALL_STATUS_VALUES.RETRYING && (
                 <>
                   <span className="fa-lg mr-1 text-danger">
-                    <i class="fas fa-exclamation-triangle"></i>
+                    <i className="fas fa-exclamation-triangle"></i>
                   </span>
                   <span className="mr-3">Retrying</span>
                 </>
diff --git a/src/wizard/Easyfix.js b/src/wizard/Easyfix.js
index 71ac755..384d63f 100644
--- a/src/wizard/Easyfix.js
+++ b/src/wizard/Easyfix.js
@@ -1,89 +1,83 @@
-import React, { Component } from "react"
+import React from "react"
 import { CollapsableCard } from "./components"
 import { Col } from "reactstrap"
 
-export default class Easyfix extends Component {
-  render() {
-    return (
-      <>
-        {Object.keys(this.props.data).map((k) => (
-          <Col sm="6">
-            <EasyfixSection title={k} data={this.props.data[k]} key={"section" + k} />
-          </Col>
-        ))}
-      </>
-    )
-  }
+export default (props) => {
+  return (
+    <>
+      {Object.keys(props.data).map((k) => (
+        <Col sm="6">
+          <EasyfixSection title={k} data={props.data[k]} key={"section" + k} />
+        </Col>
+      ))}
+    </>
+  )
 }
 
-class EasyfixSection extends Component {
-  render() {
-    var title = this.props.title
-    var subsections = Object.keys(this.props.data)
-
-    if (subsections.length > 1) {
-      subsections = Object.keys(this.props.data).map((k) => {
-        const title = (
-          <span>
-            <b>{k}</b> - {this.props.data[k][0].extra_data.description}
-          </span>
-        )
+const EasyfixSection = (props) => {
+  var title = props.title
+  var subsections = Object.keys(props.data)
 
-        return (
-          <CollapsableCard key={k} title={title} expand_class="primary" expand_text="See!">
-            <EasyfixLinksList data={this.props.data[k]} />
-          </CollapsableCard>
-        )
-      })
-      title = (
+  if (subsections.length > 1) {
+    subsections = Object.keys(props.data).map((k) => {
+      const title = (
         <span>
-          <b>{title}</b> - Is a group containing several projects. Expand to see more.
+          <b>{k}</b> - {props.data[k][0].extra_data.description}
         </span>
       )
 
       return (
-        <CollapsableCard key={title} title={title} expand_class="warning" expand_text="Expand!">
-          {subsections}
+        <CollapsableCard key={k} title={title} expand_class="primary" expand_text="See!">
+          <EasyfixLinksList data={props.data[k]} />
         </CollapsableCard>
       )
-    } else {
-      if (title !== subsections[0]) {
-        title = (
-          <span>
-            <b>{title + "/" + subsections[0]}</b> -{" "}
-            {this.props.data[subsections[0]][0].extra_data.description}
-          </span>
-        )
-      } else {
-        title = (
-          <span>
-            <b>{title}</b> - {this.props.data[subsections[0]][0].extra_data.description}
-          </span>
-        )
-      }
-      const links = Object.keys(this.props.data).map((k) => (
-        <EasyfixLinksList data={this.props.data[k]} key={"sub" + k} />
-      ))
+    })
+    title = (
+      <span>
+        <b>{title}</b> - Is a group containing several projects. Expand to see more.
+      </span>
+    )
 
-      return (
-        <CollapsableCard key={title} title={title} expand_class="primary" expand_text="See!">
-          {links}
-        </CollapsableCard>
+    return (
+      <CollapsableCard key={title} title={title} expand_class="warning" expand_text="Expand!">
+        {subsections}
+      </CollapsableCard>
+    )
+  } else {
+    if (title !== subsections[0]) {
+      title = (
+        <span>
+          <b>{title + "/" + subsections[0]}</b> -{" "}
+          {props.data[subsections[0]][0].extra_data.description}
+        </span>
+      )
+    } else {
+      title = (
+        <span>
+          <b>{title}</b> - {props.data[subsections[0]][0].extra_data.description}
+        </span>
       )
     }
+    const links = Object.keys(props.data).map((k) => (
+      <EasyfixLinksList data={props.data[k]} key={"sub" + k} />
+    ))
+
+    return (
+      <CollapsableCard key={title} title={title} expand_class="primary" expand_text="See!">
+        {links}
+      </CollapsableCard>
+    )
   }
 }
 
-class EasyfixLinksList extends Component {
-  render() {
-    const items = this.props.data.map((action) => (
-      <li key={action.extra_data.ticket_url}>
-        <a href={action.extra_data.ticket_url} target="_blank" rel="noopener noreferrer">
-          {action.name}
-        </a>
-      </li>
-    ))
+const EasyfixLinksList = (props) => {
+  const items = props.data.map((action) => (
+    <li key={action.extra_data.ticket_url}>
+      <a href={action.extra_data.ticket_url} target="_blank" rel="noopener noreferrer">
+        {action.name}
+      </a>
+    </li>
+  ))
 
-    return <ul>{items}</ul>
-  }
+  return <ul>{items}</ul>
 }
diff --git a/src/wizard/FedoraEasyKarma.js b/src/wizard/FedoraEasyKarma.js
index 830cce5..5c29c4b 100644
--- a/src/wizard/FedoraEasyKarma.js
+++ b/src/wizard/FedoraEasyKarma.js
@@ -1,137 +1,131 @@
-import React, { Component } from "react"
+import React from "react"
 import { CollapsableBadge, ModalBadge } from "./components"
 
-export default class FedoraEasyKarmaItemsList extends Component {
-  render() {
-    if (this.props.data === undefined) return null
-    else
-      return (
-        <div>
-          <h1>What is Karma</h1>
-          Before a new version of a package is pushed to the Fedora&apos;s Updates repository, it
-          needs to be tested and proved functional.{" "}
-          <CollapsableBadge expand_text="Tell me more about the process!">
-            The updates are kept in{" "}
-            <a target="_blank" rel="noopener noreferrer" href="https://bodhi.fedoraproject.org/">
-              Bodhi
-            </a>
-            , which acts as a gatekeeper between new package releases and the stable repositories.{" "}
-            Users (or automated systems) can then provide feedback in form of positive/negative
-            Karma, marking the update as working (or not) within the scope of their expectations.{" "}
-            An update can (and usually does) consist of several packages (rpms), that are going
-            through the acceptance process together.
-          </CollapsableBadge>
-          <h1 style={{ marginTop: 1 + "em" }}>Sure, let me do it!</h1>
-          <ol className="steps">
-            <li>
-              Fedora Accounts System (FAS) account is required.{" "}
-              <CollapsableBadge expand_text="Don&#39;t have one yet?">
-                <ul>
+export default (props) => {
+  if (props.data === undefined) return null
+  else
+    return (
+      <div>
+        <h1>What is Karma</h1>
+        Before a new version of a package is pushed to the Fedora&apos;s Updates repository, it
+        needs to be tested and proved functional.{" "}
+        <CollapsableBadge expand_text="Tell me more about the process!">
+          The updates are kept in{" "}
+          <a target="_blank" rel="noopener noreferrer" href="https://bodhi.fedoraproject.org/">
+            Bodhi
+          </a>
+          , which acts as a gatekeeper between new package releases and the stable repositories.{" "}
+          Users (or automated systems) can then provide feedback in form of positive/negative
+          Karma, marking the update as working (or not) within the scope of their expectations. An
+          update can (and usually does) consist of several packages (rpms), that are going through
+          the acceptance process together.
+        </CollapsableBadge>
+        <h1 style={{ marginTop: 1 + "em" }}>Sure, let me do it!</h1>
+        <ol className="steps">
+          <li>
+            Fedora Accounts System (FAS) account is required.{" "}
+            <CollapsableBadge expand_text="Don&#39;t have one yet?">
+              <ul>
+                <li>
+                  Visit{" "}
+                  <a
+                    target="_blank"
+                    rel="noopener noreferrer"
+                    href="https://admin.fedoraproject.org/accounts/user/new">
+                    FAS Sign-up page
+                  </a>{" "}
+                  and create it.
+                </li>
+                <li>Note the username and password, you will need it later on.</li>
+              </ul>
+            </CollapsableBadge>
+          </li>
+          <li>
+            Make sure your system is up-to-date: <code>sudo dnf update --refresh</code>
+          </li>
+          <li>
+            Install fedora-easy-karma tool: <code>sudo dnf install fedora-easy-karma</code>
+          </li>
+          <li>
+            Choose an update to test{" "}
+            <CollapsableBadge expand_text="Not sure how?">
+              Have a look at the available packages in <code>updates-testing</code> repo, by
+              running <code>dnf --enablerepo=updates-testing list --refresh --upgrades</code> and
+              choose a package you know.
+            </CollapsableBadge>
+          </li>
+          <li>
+            Install the package{" "}
+            <code>sudo dnf --enablerepo=updates-testing update PACKAGE_NAME</code>, and test
+            whether it works, as you would expect.
+            <br />
+            <strong>Note:</strong> Other packages from <code>updates-testing</code> repo may be
+            installed as dependencies (shown during the installation process). Try to test those
+            too, if possible.{" "}
+            <CollapsableBadge expand_text="Need some tips?">
+              Sometimes, the update associated with the package you just installed fixes some
+              specific bugs, or has testcases associated with it.
+              <br />
+              Run <code>fedora-easy-karma --fas-username=FAS_USERNAME</code>, and look for{" "}
+              <code>Bugs</code>, <code>Test Cases</code>, and/or <code>Notes</code> sections in the
+              detailed output.{" "}
+              <ModalBadge expand_text="Want something a bit nicer?">
+                We already mentioned Bodhi, several times. Instead of using the{" "}
+                <code>fedora-easy-karma</code> interface for submitting Karma and/or learning about
+                the Update, you can visit Bodhi directly.
+                <br />
+                <code>fedora-easy-karma</code> shows the URL of the relevant update near the bottom
+                of the text output - look for URL like{" "}
+                <code>https://bodhi.fedoraproject.org/updates/FEDORA-2019-00870e8bfc</code>.
+                <br />
+                You can have a look at other people's comments, the afore-mentioned Bugs or Test
+                Cases, and even submit the Karma directly. Just use your FAS credentials to log-in.
+              </ModalBadge>
+            </CollapsableBadge>
+          </li>
+          <li>
+            Run <code>fedora-easy-karma --fas-username=FAS_USERNAME</code> and report what you
+            found out.{" "}
+            <CollapsableBadge expand_text="New to fedora-easy-karma?">
+              It identifies the packages installed from the <code>updates-testing</code>{" "}
+              repository, and matches them to the updates in Bodhi.
+              <br />
+              You are then presented with the relevant updates one-by-one, to submit Karma and a
+              comment.{" "}
+              <ModalBadge expand_text="Not sure what Karma means?">
+                <ol>
                   <li>
-                    Visit{" "}
+                    Enter <code>1</code> to mark positive karma (the update works just fine, as far
+                    as you can tell), or <code>-1</code> to mark the package as broken. <br />
+                    Not sure you can judge the package's state? Have a look at the{" "}
                     <a
                       target="_blank"
-                      rel="noopener noreferrer"
-                      href="https://admin.fedoraproject.org/accounts/user/new">
-                      FAS Sign-up page
-                    </a>{" "}
-                    and create it.
+                      href="https://fedoraproject.org/wiki/QA:Update_feedback_guidelines"
+                      rel="noopener noreferrer">
+                      Update Feedback Guidelines
+                    </a>
+                    <br />
+                    Still not sure? Just press <code>Enter</code> to skip it.
                   </li>
-                  <li>Note the username and password, you will need it later on.</li>
-                </ul>
-              </CollapsableBadge>
-            </li>
-            <li>
-              Make sure your system is up-to-date: <code>sudo dnf update --refresh</code>
-            </li>
-            <li>
-              Install fedora-easy-karma tool: <code>sudo dnf install fedora-easy-karma</code>
-            </li>
-            <li>
-              Choose an update to test{" "}
-              <CollapsableBadge expand_text="Not sure how?">
-                Have a look at the available packages in <code>updates-testing</code> repo, by
-                running <code>dnf --enablerepo=updates-testing list --refresh --upgrades</code> and
-                choose a package you know.
-              </CollapsableBadge>
-            </li>
-            <li>
-              Install the package{" "}
-              <code>sudo dnf --enablerepo=updates-testing update PACKAGE_NAME</code>, and test
-              whether it works, as you would expect.
-              <br />
-              <strong>Note:</strong> Other packages from <code>updates-testing</code> repo may be
-              installed as dependencies (shown during the installation process). Try to test those
-              too, if possible.{" "}
-              <CollapsableBadge expand_text="Need some tips?">
-                Sometimes, the update associated with the package you just installed fixes some
-                specific bugs, or has testcases associated with it.
-                <br />
-                Run <code>fedora-easy-karma --fas-username=FAS_USERNAME</code>, and look for{" "}
-                <code>Bugs</code>, <code>Test Cases</code>, and/or <code>Notes</code> sections in
-                the detailed output.{" "}
-                <ModalBadge expand_text="Want something a bit nicer?">
-                  We already mentioned Bodhi, several times. Instead of using the{" "}
-                  <code>fedora-easy-karma</code> interface for submitting Karma and/or learning
-                  about the Update, you can visit Bodhi directly.
-                  <br />
-                  <code>fedora-easy-karma</code> shows the URL of the relevant update near the
-                  bottom of the text output - look for URL like{" "}
-                  <code>https://bodhi.fedoraproject.org/updates/FEDORA-2019-00870e8bfc</code>.
-                  <br />
-                  You can have a look at other people's comments, the afore-mentioned Bugs or Test
-                  Cases, and even submit the Karma directly. Just use your FAS credentials to
-                  log-in.
-                </ModalBadge>
-              </CollapsableBadge>
-            </li>
-            <li>
-              Run <code>fedora-easy-karma --fas-username=FAS_USERNAME</code> and report what you
-              found out.{" "}
-              <CollapsableBadge expand_text="New to fedora-easy-karma?">
-                It identifies the packages installed from the <code>updates-testing</code>{" "}
-                repository, and matches them to the updates in Bodhi.
-                <br />
-                You are then presented with the relevant updates one-by-one, to submit Karma and a
-                comment.{" "}
-                <ModalBadge expand_text="Not sure what Karma means?">
-                  <ol>
-                    <li>
-                      Enter <code>1</code> to mark positive karma (the update works just fine, as
-                      far as you can tell), or <code>-1</code> to mark the package as broken.{" "}
-                      <br />
-                      Not sure you can judge the package's state? Have a look at the{" "}
-                      <a
-                        target="_blank"
-                        href="https://fedoraproject.org/wiki/QA:Update_feedback_guidelines"
-                        rel="noopener noreferrer">
-                        Update Feedback Guidelines
-                      </a>
-                      <br />
-                      Still not sure? Just press <code>Enter</code> to skip it.
-                    </li>
-                    <li>
-                      Add a comment - even if it works, try to describe what you tested. It can be
-                      as easy as{" "}
-                      <code>I tried openning and editing a document, and it worked.</code> when you
-                      test a text-editor, or{" "}
-                      <code>I opened a couple of tabs, and browsed random pages.</code> for a
-                      web-browser.
-                      <br />
-                      Absolutely make sure to provide reasonable amount of detail, when submitting
-                      negative karma - ideally, you should also create a bugreport, and reference
-                      it in the comment.
-                    </li>
-                  </ol>
-                </ModalBadge>
-              </CollapsableBadge>
-            </li>
-            <li>
-              Restore the stable-packages on your system by running{" "}
-              <code>sudo dnf distro-sync</code>
-            </li>
-          </ol>
-        </div>
-      )
-  }
+                  <li>
+                    Add a comment - even if it works, try to describe what you tested. It can be as
+                    easy as <code>I tried openning and editing a document, and it worked.</code>{" "}
+                    when you test a text-editor, or{" "}
+                    <code>I opened a couple of tabs, and browsed random pages.</code> for a
+                    web-browser.
+                    <br />
+                    Absolutely make sure to provide reasonable amount of detail, when submitting
+                    negative karma - ideally, you should also create a bugreport, and reference it
+                    in the comment.
+                  </li>
+                </ol>
+              </ModalBadge>
+            </CollapsableBadge>
+          </li>
+          <li>
+            Restore the stable-packages on your system by running <code>sudo dnf distro-sync</code>
+          </li>
+        </ol>
+      </div>
+    )
 }
diff --git a/src/wizard/FedoraManualTesting.js b/src/wizard/FedoraManualTesting.js
index 10de4c2..aca861a 100644
--- a/src/wizard/FedoraManualTesting.js
+++ b/src/wizard/FedoraManualTesting.js
@@ -1,408 +1,382 @@
-import React, { Component } from "react"
+import React, { useState } from "react"
 import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap"
 import { CollapsableCard, ModalBadge } from "./components"
 
-export default class FedoraManualTesting extends Component {
-  render() {
-    let sections = Object.keys(this.props.data).map((k) => (
-      <FedoraManualTestingItemsListSub1 title={k} data={this.props.data[k]} key={k} />
-    ))
-    return <div>{sections}</div>
-  }
+export default (props) => {
+  let sections = Object.keys(props.data).map((k) => (
+    <FedoraManualTestingItemsListSub1 title={k} data={props.data[k]} key={k} />
+  ))
+  return <div>{sections}</div>
 }
 
-class FedoraManualTestingItemsListSub2 extends Component {
-  render() {
-    return (
-      <ul>
-        {this.props.data.map((action) => (
-          <li>
-            <FedoraManualTestingItem data={action} />
-          </li>
-        ))}
-      </ul>
-    )
-  }
+const FedoraManualTestingItemsListSub2 = (props) => {
+  return (
+    <ul>
+      {props.data.map((action) => (
+        <li>
+          <FedoraManualTestingItem data={action} />
+        </li>
+      ))}
+    </ul>
+  )
 }
 
-export class FedoraManualTestingItemsListSub1 extends Component {
-  render() {
-    var subsections = Object.keys(this.props.data).map((k) => (
-      <li key={"li" + k}>
-        <span>{k}</span>
-        <FedoraManualTestingItemsListSub2 data={this.props.data[k]} key={this.props.data[k]} />
-      </li>
-    ))
-    subsections = <ul>{subsections}</ul>
+export function FedoraManualTestingItemsListSub1(props) {
+  var subsections = Object.keys(props.data).map((k) => (
+    <li key={"li" + k}>
+      <span>{k}</span>
+      <FedoraManualTestingItemsListSub2 data={props.data[k]} key={props.data[k]} />
+    </li>
+  ))
+  subsections = <ul>{subsections}</ul>
 
-    var l1 = <div></div>
-    switch (this.props.title) {
-      case "Installation":
-        l1 = (
-          <div>
-            The <strong>Installation</strong> testcases generally deal with a part of the
-            installation procedure.
-            <br />
-            You will certainly need an installation ISO, and either a Virtual or Bare-metal machine
-            to run the test.
-            <br />
-            <i>Note:</i> some (not that many, though) of these testcases require Bare-metal
-            machine. Be sure to read the Description of the testcase carefully.
-          </div>
-        )
-        break
-      case "Desktop":
-        l1 = (
-          <div>
-            The <strong>Desktop</strong> testcases cover basic functionality of the desktop
-            environment.
-            <br />
-            You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live
-            image instead.
-          </div>
-        )
-        break
-      case "Base":
-        l1 = (
-          <div>
-            The <strong>Base</strong> testcases cover the system&#x27;s basic functionality just
-            after a clean installation.
-            <br />
-            Most times, you will be asked to perform a clean Fedora installation. You can use
-            either Virtual or Bare-metal machine.
-            <br />
-            <i>Pro tip:</i> using a snapshot of cleanly installed Virtual machine is just fine. No
-            need to reinstall for every testcase.
-          </div>
-        )
-        break
-      case "Server":
-        l1 = (
-          <div>
-            The <strong>Server</strong> testcases usually require multiple machines to test the
-            server-client behaviour, and might feel a bit advanced.
-          </div>
-        )
-        break
-      case "Cloud":
-        l1 = (
-          <div>
-            Even thought the <strong>Cloud</strong> testcases are best done in the specific
-            environments like EC2 or Openstack, you can also perform them locally using Testcloud.
-            <br />
-            Have a look at the{" "}
-            <a
-              target="_blank"
-              rel="noopener noreferrer"
-              href="https://fedoraproject.org/wiki/Test_Results:Fedora_Current_Cloud#Cloud_Provider_Setup">
-              Cloud provider setup
-            </a>{" "}
-            guides for more details.
-          </div>
-        )
-        break
-      default:
-        break
-    }
-
-    return (
-      <CollapsableCard title={l1} expand_text="See" expand_class="primary">
-        {subsections}
-      </CollapsableCard>
-    )
+  var l1 = <div></div>
+  switch (props.title) {
+    case "Installation":
+      l1 = (
+        <div>
+          The <strong>Installation</strong> testcases generally deal with a part of the
+          installation procedure.
+          <br />
+          You will certainly need an installation ISO, and either a Virtual or Bare-metal machine
+          to run the test.
+          <br />
+          <i>Note:</i> some (not that many, though) of these testcases require Bare-metal machine.
+          Be sure to read the Description of the testcase carefully.
+        </div>
+      )
+      break
+    case "Desktop":
+      l1 = (
+        <div>
+          The <strong>Desktop</strong> testcases cover basic functionality of the desktop
+          environment.
+          <br />
+          You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live
+          image instead.
+        </div>
+      )
+      break
+    case "Base":
+      l1 = (
+        <div>
+          The <strong>Base</strong> testcases cover the system&#x27;s basic functionality just
+          after a clean installation.
+          <br />
+          Most times, you will be asked to perform a clean Fedora installation. You can use either
+          Virtual or Bare-metal machine.
+          <br />
+          <i>Pro tip:</i> using a snapshot of cleanly installed Virtual machine is just fine. No
+          need to reinstall for every testcase.
+        </div>
+      )
+      break
+    case "Server":
+      l1 = (
+        <div>
+          The <strong>Server</strong> testcases usually require multiple machines to test the
+          server-client behaviour, and might feel a bit advanced.
+        </div>
+      )
+      break
+    case "Cloud":
+      l1 = (
+        <div>
+          Even thought the <strong>Cloud</strong> testcases are best done in the specific
+          environments like EC2 or Openstack, you can also perform them locally using Testcloud.
+          <br />
+          Have a look at the{" "}
+          <a
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://fedoraproject.org/wiki/Test_Results:Fedora_Current_Cloud#Cloud_Provider_Setup">
+            Cloud provider setup
+          </a>{" "}
+          guides for more details.
+        </div>
+      )
+      break
+    default:
+      break
   }
+
+  return (
+    <CollapsableCard title={l1} expand_text="See" expand_class="primary">
+      {subsections}
+    </CollapsableCard>
+  )
 }
 
-export class FedoraManualTestingItem extends Component {
-  render() {
-    const extra_data = this.props.data.extra_data
+export function FedoraManualTestingItem(props) {
+  const extra_data = props.data.extra_data
 
-    const tc_url = extra_data.testcase_url
-    const name = this.props.data.name
+  const tc_url = extra_data.testcase_url
+  const name = props.data.name
 
-    const matrix_url = extra_data.matrix_url
-    var environment_examples = undefined
-    switch (extra_data.testtype) {
-      case "Installation":
-        environment_examples = (
-          <span>
-            <code>x86_64</code> or <code>ARM</code>
-          </span>
-        )
-        break
-      case "Base":
-        environment_examples = (
-          <span>
-            <code>Workstation</code>, <code>Server</code>, <code>Xfce</code> or{" "}
-            <code>Minimal</code>
-          </span>
-        )
-        break
-      case "Desktop":
-        environment_examples = (
-          <span>
-            <code>Workstation</code> or <code>KDE</code>
-          </span>
-        )
-        break
-      case "Server":
-        environment_examples = (
-          <span>
-            <code>x86_64</code> or <code>aarch64</code>
-          </span>
-        )
-        break
-      default:
-        break
-    }
+  const matrix_url = extra_data.matrix_url
+  var environment_examples = undefined
+  switch (extra_data.testtype) {
+    case "Installation":
+      environment_examples = (
+        <span>
+          <code>x86_64</code> or <code>ARM</code>
+        </span>
+      )
+      break
+    case "Base":
+      environment_examples = (
+        <span>
+          <code>Workstation</code>, <code>Server</code>, <code>Xfce</code> or <code>Minimal</code>
+        </span>
+      )
+      break
+    case "Desktop":
+      environment_examples = (
+        <span>
+          <code>Workstation</code> or <code>KDE</code>
+        </span>
+      )
+      break
+    case "Server":
+      environment_examples = (
+        <span>
+          <code>x86_64</code> or <code>aarch64</code>
+        </span>
+      )
+      break
+    default:
+      break
+  }
 
-    const testtype = extra_data.testtype
+  const testtype = extra_data.testtype
 
-    return (
-      <ModalInfo buttonLabel={name}>
-        <ol className="steps">
-          <li>
-            Identify the testcase and `environment` in our{" "}
-            <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
-              Tescase matrix
-            </a>{" "}
-            <ModalBadge expand_text="Not sure what that means?">
-              <ul>
-                <li>
-                  Have a look at the matrix. The rows are the testcases, and the columns are the
-                  environments. Most of the time, these are {environment_examples} for the{" "}
-                  {testtype} testcases, but you can also encouter a generic <code>Result</code>{" "}
-                  column, which usually means you can use any media/architecture available.
-                </li>
-                <li>
-                  For this particular testcase, <code>{extra_data.envs.join(", ")}</code>{" "}
-                  {extra_data.envs.length > 1 ? "environments are" : "environment is"} missing
-                  results.
-                </li>
-              </ul>
-            </ModalBadge>
-          </li>
+  return (
+    <ModalInfo buttonLabel={name}>
+      <ol className="steps">
+        <li>
+          Identify the testcase and `environment` in our{" "}
+          <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
+            Tescase matrix
+          </a>{" "}
+          <ModalBadge expand_text="Not sure what that means?">
+            <ul>
+              <li>
+                Have a look at the matrix. The rows are the testcases, and the columns are the
+                environments. Most of the time, these are {environment_examples} for the {testtype}{" "}
+                testcases, but you can also encouter a generic <code>Result</code> column, which
+                usually means you can use any media/architecture available.
+              </li>
+              <li>
+                For this particular testcase, <code>{extra_data.envs.join(", ")}</code>{" "}
+                {extra_data.envs.length > 1 ? "environments are" : "environment is"} missing
+                results.
+              </li>
+            </ul>
+          </ModalBadge>
+        </li>
 
-          <li>
-            Read the{" "}
-            <a target="_blank" rel="noopener noreferrer" href={tc_url}>
-              Testcase
-            </a>{" "}
-            briefly, just to have a general idea of what you will be doing.{" "}
-            <ModalBadge expand_text="Not making much sense?">
-              The testcases are generally split into four sections:
-              <ul>
-                <li>
-                  <strong>Description</strong> should give you a general idea of what is being
-                  tested
-                </li>
-                <li>
-                  <strong>Setup</strong> describes the steps to take before you begin working on
-                  the testcase
-                </li>
-                <li>
-                  <strong>How to test</strong> contains the individual steps to take in order to
-                  perform the testcase
-                </li>
-                <li>
-                  <strong>Expected results</strong> describe what you should check while testing in
-                  order to decide whether it Passed of Failed
-                </li>
-              </ul>
-            </ModalBadge>
-          </li>
+        <li>
+          Read the{" "}
+          <a target="_blank" rel="noopener noreferrer" href={tc_url}>
+            Testcase
+          </a>{" "}
+          briefly, just to have a general idea of what you will be doing.{" "}
+          <ModalBadge expand_text="Not making much sense?">
+            The testcases are generally split into four sections:
+            <ul>
+              <li>
+                <strong>Description</strong> should give you a general idea of what is being tested
+              </li>
+              <li>
+                <strong>Setup</strong> describes the steps to take before you begin working on the
+                testcase
+              </li>
+              <li>
+                <strong>How to test</strong> contains the individual steps to take in order to
+                perform the testcase
+              </li>
+              <li>
+                <strong>Expected results</strong> describe what you should check while testing in
+                order to decide whether it Passed of Failed
+              </li>
+            </ul>
+          </ModalBadge>
+        </li>
 
-          <li>
-            Based on the enviromnent, select and download and appropriate ISO{" "}
-            <a
-              target="_blank"
-              rel="noopener noreferrer"
-              href="https://fedoraproject.org/wiki/Test_Results:Current_Installation_Test#How_to_test">
-              here
-            </a>
-            .{" "}
-            <ModalBadge expand_text="Not sure how?">
-              <ul>
-                <li>
-                  Most of the time Workstation Live, or Server DVD are fine, but sometimes there
-                  are specific products (e.g. Xfce) to be tested
-                </li>
-                <li>
-                  Make sure to read about identifying the environment above.{" "}
-                  <ModalBadge expand_text="See">
-                    <ul>
-                      <li>
-                        Have a look at the matrix. The rows are the testcases, and the columns are
-                        the environments. Most of the time, these are {environment_examples} for
-                        the {testtype} testcases, but you can also encouter a generic{" "}
-                        <code>Result</code> column, which usually means you can use any
-                        media/architecture available.
-                      </li>
-                      <li>
-                        For this particular testcase, <code>{extra_data.envs.join(", ")}</code>{" "}
-                        {extra_data.envs.length > 1 ? "environments are" : "environment is"}{" "}
-                        missing results.
-                      </li>
-                    </ul>
-                  </ModalBadge>
-                </li>
-              </ul>
-            </ModalBadge>
-          </li>
+        <li>
+          Based on the enviromnent, select and download and appropriate ISO{" "}
+          <a
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://fedoraproject.org/wiki/Test_Results:Current_Installation_Test#How_to_test">
+            here
+          </a>
+          .{" "}
+          <ModalBadge expand_text="Not sure how?">
+            <ul>
+              <li>
+                Most of the time Workstation Live, or Server DVD are fine, but sometimes there are
+                specific products (e.g. Xfce) to be tested
+              </li>
+              <li>
+                Make sure to read about identifying the environment above.{" "}
+                <ModalBadge expand_text="See">
+                  <ul>
+                    <li>
+                      Have a look at the matrix. The rows are the testcases, and the columns are
+                      the environments. Most of the time, these are {environment_examples} for the{" "}
+                      {testtype} testcases, but you can also encouter a generic <code>Result</code>{" "}
+                      column, which usually means you can use any media/architecture available.
+                    </li>
+                    <li>
+                      For this particular testcase, <code>{extra_data.envs.join(", ")}</code>{" "}
+                      {extra_data.envs.length > 1 ? "environments are" : "environment is"} missing
+                      results.
+                    </li>
+                  </ul>
+                </ModalBadge>
+              </li>
+            </ul>
+          </ModalBadge>
+        </li>
 
-          <li>
-            Study the{" "}
-            <a target="_blank" rel="noopener noreferrer" href={tc_url}>
-              Testcase
-            </a>{" "}
-            thoroughly, to be sure you know what to do.{" "}
-            <ModalBadge expand_text="Feeling a bit lost?">
-              <ul>
-                <li>
-                  The testcase structure is not making sense?{" "}
-                  <ModalBadge expand_text="Click here">
-                    The testcases are generally split into four sections:
-                    <ul>
-                      <li>
-                        <strong>Description</strong> should give you a general idea of what is
-                        being tested
-                      </li>
-                      <li>
-                        <strong>Setup</strong> describes the steps to take before you begin working
-                        on the testcase
-                      </li>
-                      <li>
-                        <strong>How to test</strong> contains the individual steps to take in order
-                        to perform the testcase
-                      </li>
-                      <li>
-                        <strong>Expected results</strong> describe what you should check while
-                        testing in order to decide whether it Passed of Failed
-                      </li>
-                    </ul>
-                  </ModalBadge>
-                </li>
-                <li>
-                  Maybe you are stuck, or just do not understand something? Feel free to ask on our
-                  IRC channel #fedora-qa at freenode.net{" "}
-                  <ModalBadge expand_text="Don&#39;t have an IRC client?">
-                    If you are not that familiar with IRC, you can use the{" "}
-                    <a
-                      target="_blank"
-                      rel="noopener noreferrer"
-                      href="http://webchat.freenode.net">
-                      web-interface
-                    </a>{" "}
-                    just enter a Nickname of your choice, #fedora-qa (including the hash sign) in
-                    the Channels field, and click Connect.
-                  </ModalBadge>
-                </li>
-              </ul>
-            </ModalBadge>
-          </li>
+        <li>
+          Study the{" "}
+          <a target="_blank" rel="noopener noreferrer" href={tc_url}>
+            Testcase
+          </a>{" "}
+          thoroughly, to be sure you know what to do.{" "}
+          <ModalBadge expand_text="Feeling a bit lost?">
+            <ul>
+              <li>
+                The testcase structure is not making sense?{" "}
+                <ModalBadge expand_text="Click here">
+                  The testcases are generally split into four sections:
+                  <ul>
+                    <li>
+                      <strong>Description</strong> should give you a general idea of what is being
+                      tested
+                    </li>
+                    <li>
+                      <strong>Setup</strong> describes the steps to take before you begin working
+                      on the testcase
+                    </li>
+                    <li>
+                      <strong>How to test</strong> contains the individual steps to take in order
+                      to perform the testcase
+                    </li>
+                    <li>
+                      <strong>Expected results</strong> describe what you should check while
+                      testing in order to decide whether it Passed of Failed
+                    </li>
+                  </ul>
+                </ModalBadge>
+              </li>
+              <li>
+                Maybe you are stuck, or just do not understand something? Feel free to ask on our
+                IRC channel #fedora-qa at freenode.net{" "}
+                <ModalBadge expand_text="Don&#39;t have an IRC client?">
+                  If you are not that familiar with IRC, you can use the{" "}
+                  <a target="_blank" rel="noopener noreferrer" href="http://webchat.freenode.net">
+                    web-interface
+                  </a>{" "}
+                  just enter a Nickname of your choice, #fedora-qa (including the hash sign) in the
+                  Channels field, and click Connect.
+                </ModalBadge>
+              </li>
+            </ul>
+          </ModalBadge>
+        </li>
 
-          <li>Get your hands dirty, and test the hell out of it!</li>
-          <li>
-            <ModalBadge expand_class="success" expand_text="Everything went well" type="btn">
-              Great! Either use <code>relval report-results</code> on command line (make sure to
-              install the <code>relval</code> package first), or modify the{" "}
-              <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
-                matrix
-              </a>{" "}
-              directly by clicking on the <code>Edit</code> link next to the Matrice's header, and
-              put <code>&#123;&#123;result|pass|YOUR_NAME_HERE|&#125;&#125;</code> in the
-              appropriate spot.
-            </ModalBadge>
+        <li>Get your hands dirty, and test the hell out of it!</li>
+        <li>
+          <ModalBadge expand_class="success" expand_text="Everything went well" type="btn">
+            Great! Either use <code>relval report-results</code> on command line (make sure to
+            install the <code>relval</code> package first), or modify the{" "}
+            <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
+              matrix
+            </a>{" "}
+            directly by clicking on the <code>Edit</code> link next to the Matrice's header, and
+            put <code>&#123;&#123;result|pass|YOUR_NAME_HERE|&#125;&#125;</code> in the appropriate
+            spot.
+          </ModalBadge>
 
-            <ModalBadge expand_class="danger" expand_text="I found a bug!" type="btn">
-              Awesome! Ideally read up on https://fedoraproject.org/wiki/How_to_file_a_bug_report
-              <br />
-              If you don't feel like reading a wall of text, at least pot together a small document
-              containing:
-              <ul>
-                <li>
-                  Brief description of what went wrong (e.g. "QA:Testcase_dualboot_with_windows -
-                  Bootloader does not show the Windows option")
-                </li>
-                <li>
-                  The name of the ISO image you used (e.g.
-                  "Fedora-Server-netinst-i386-Rawhide-20181227.n.0.iso")
-                </li>
-                <li>
-                  Note what you did, as precisely as possible, in a step-by-step fashion. Even
-                  details like "Chose Polish as the languae for the installation process" can
-                  matter.
-                </li>
-                <li>
-                  Try to reproduce the same state again based on the steps above (you can also
-                  experiment a bit, and try to come up with just the critical steps)
-                </li>
-                <li>
-                  Share your notes on the internet (you can use fpaste), and ask for help with
-                  filing the bug report on our IRC channel #fedora-qa at freenode.net{" "}
-                  <ModalBadge expand_text="Don&#39;t have an IRC client?">
-                    If you are not that familiar with IRC, you can use the web-interface[link] just
-                    enter a Nickname of your choice, #fedora-qa (including the hash sign) in the
-                    Channels field, and click Connect.
-                  </ModalBadge>
-                </li>
-              </ul>
-              Once you get the Bug reported, make sure to also submit the result into the testing
-              matrix. Either use <code>relval report-results</code> on command line (make sure to
-              install the <code>relval</code> package first), or modify the{" "}
-              <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
-                matrix
-              </a>{" "}
-              directly by clicking on the <code>Edit</code> link next to the Matrice's header, and
-              put <code>&#123;&#123;result|fail|YOUR_NAME_HERE|BUG_NUMBER|&#125;&#125;</code> in
-              the appropriate spot.
-            </ModalBadge>
-          </li>
-        </ol>
-      </ModalInfo>
-    )
-  }
+          <ModalBadge expand_class="danger" expand_text="I found a bug!" type="btn">
+            Awesome! Ideally read up on https://fedoraproject.org/wiki/How_to_file_a_bug_report
+            <br />
+            If you don't feel like reading a wall of text, at least pot together a small document
+            containing:
+            <ul>
+              <li>
+                Brief description of what went wrong (e.g. "QA:Testcase_dualboot_with_windows -
+                Bootloader does not show the Windows option")
+              </li>
+              <li>
+                The name of the ISO image you used (e.g.
+                "Fedora-Server-netinst-i386-Rawhide-20181227.n.0.iso")
+              </li>
+              <li>
+                Note what you did, as precisely as possible, in a step-by-step fashion. Even
+                details like "Chose Polish as the languae for the installation process" can matter.
+              </li>
+              <li>
+                Try to reproduce the same state again based on the steps above (you can also
+                experiment a bit, and try to come up with just the critical steps)
+              </li>
+              <li>
+                Share your notes on the internet (you can use fpaste), and ask for help with filing
+                the bug report on our IRC channel #fedora-qa at freenode.net{" "}
+                <ModalBadge expand_text="Don&#39;t have an IRC client?">
+                  If you are not that familiar with IRC, you can use the web-interface[link] just
+                  enter a Nickname of your choice, #fedora-qa (including the hash sign) in the
+                  Channels field, and click Connect.
+                </ModalBadge>
+              </li>
+            </ul>
+            Once you get the Bug reported, make sure to also submit the result into the testing
+            matrix. Either use <code>relval report-results</code> on command line (make sure to
+            install the <code>relval</code> package first), or modify the{" "}
+            <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
+              matrix
+            </a>{" "}
+            directly by clicking on the <code>Edit</code> link next to the Matrice's header, and
+            put <code>&#123;&#123;result|fail|YOUR_NAME_HERE|BUG_NUMBER|&#125;&#125;</code> in the
+            appropriate spot.
+          </ModalBadge>
+        </li>
+      </ol>
+    </ModalInfo>
+  )
 }
 
-class ModalInfo extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      modal: false,
-    }
+function ModalInfo(props) {
+  const [state, setState] = useState({
+    modal: false,
+  })
 
-    this.toggle = this.toggle.bind(this)
-  }
-
-  toggle(e) {
-    this.setState({
-      modal: !this.state.modal,
+  const toggle = (e) => {
+    setState({
+      modal: !state.modal,
     })
     e.preventDefault()
   }
 
-  render() {
-    const project = this.props.buttonLabel.split(":")[0]
-    const ticket = this.props.buttonLabel.split(":")[1] //strip whitespace?
+  const project = props.buttonLabel.split(":")[0]
+  const ticket = props.buttonLabel.split(":")[1] //strip whitespace?
 
-    return (
-      <div>
-        <a href="/#" onClick={(e) => this.toggle(e)}>
-          {this.props.buttonLabel}
-        </a>
-        <Modal
-          isOpen={this.state.modal}
-          toggle={this.toggle}
-          className={this.props.className}
-          size="lg">
-          <ModalHeader toggle={this.toggle}>{project}</ModalHeader>
-          <ModalBody>
-            <h1>{ticket}</h1>
-            {this.props.children}
-          </ModalBody>
-          <ModalFooter></ModalFooter>
-        </Modal>
-      </div>
-    )
-  }
+  return (
+    <div>
+      <a href="/#" onClick={(e) => toggle(e)}>
+        {props.buttonLabel}
+      </a>
+      <Modal isOpen={state.modal} toggle={toggle} className={props.className} size="lg">
+        <ModalHeader toggle={toggle}>{project}</ModalHeader>
+        <ModalBody>
+          <h1>{ticket}</h1>
+          {props.children}
+        </ModalBody>
+        <ModalFooter></ModalFooter>
+      </Modal>
+    </div>
+  )
 }
diff --git a/src/wizard/components.js b/src/wizard/components.js
index 85b7471..7e91f72 100644
--- a/src/wizard/components.js
+++ b/src/wizard/components.js
@@ -1,4 +1,4 @@
-import React, { Component } from "react"
+import React, { useState } from "react"
 import {
   Card,
   CardHeader,
@@ -12,102 +12,76 @@ import {
 } from "reactstrap"
 import uniqueID from "../helpers/uniqueID"
 
-class CollapsableCard extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      showModal: false,
-    }
-    this.toggleModal = this.toggleModal.bind(this)
-  }
-
-  toggleModal() {
-    let modalState = !this.state.showModal
-    this.setState({
-      showModal: modalState,
-    })
-  }
-
-  render() {
-    const { title, expand_text, expand_class, children } = this.props
-    const id = uniqueID("collapsable-card-id-")
-    return (
-      <Card>
-        <CardHeader>
-          <Row>
-            <div className="col-sm-10">{title}</div>
-            <div className="col-sm-2">
-              <Toggler id={id} color={expand_class} text={expand_text} />
-            </div>
-          </Row>
-        </CardHeader>
-        <UncontrolledCollapse toggler={"#" + id}>
-          <CardBody>{children}</CardBody>
-        </UncontrolledCollapse>
-      </Card>
-    )
-  }
+const CollapsableCard = (props) => {
+  const { title, expand_text, expand_class, children } = props
+  const id = uniqueID("collapsable-card-id-")
+  return (
+    <Card>
+      <CardHeader>
+        <Row>
+          <div className="col-sm-10">{title}</div>
+          <div className="col-sm-2">
+            <Toggler id={id} color={expand_class} text={expand_text} />
+          </div>
+        </Row>
+      </CardHeader>
+      <UncontrolledCollapse toggler={"#" + id}>
+        <CardBody>{children}</CardBody>
+      </UncontrolledCollapse>
+    </Card>
+  )
 }
 
-class CollapsableBadge extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      showModal: false,
-    }
-    this.toggleModal = this.toggleModal.bind(this)
-  }
+const CollapsableBadge = (props) => {
+  const [state, setState] = useState({ showModal: false })
 
-  toggleModal() {
-    let modalState = !this.state.showModal
-    this.setState({
+  const toggleModal = () => {
+    let modalState = !state.showModal
+    setState({
       showModal: modalState,
     })
   }
-  render() {
-    const { expand_text, expand_class, children, type } = this.props
-    const id = uniqueID("collapsable-badge-id-")
-    return (
-      <span>
-        <Button
-          className={type + " " + type + "-" + expand_class}
-          href="#"
-          id={id}
-          color="primary"
-          onClick={this.toggleModal}>
-          {expand_text}
-        </Button>{" "}
-        <Modal isOpen={this.state.showModal} toggle={this.toggleModal}>
-          <ModalBody>{children}</ModalBody>
-          <ModalFooter>
-            <Button color="primary" onClick={this.toggleModal}>
-              Close <i class="fas fa-times-circle"></i>
-            </Button>
-          </ModalFooter>
-        </Modal>
-      </span>
-    )
-  }
+
+  const { expand_text, expand_class, children, type } = props
+  const id = uniqueID("collapsable-badge-id-")
+  return (
+    <span>
+      <Button
+        className={type + " " + type + "-" + expand_class}
+        href="#"
+        id={id}
+        color="primary"
+        onClick={toggleModal}>
+        {expand_text}
+      </Button>{" "}
+      <Modal isOpen={state.showModal} toggle={toggleModal}>
+        <ModalBody>{children}</ModalBody>
+        <ModalFooter>
+          <Button color="primary" onClick={toggleModal}>
+            Close <i class="fas fa-times-circle"></i>
+          </Button>
+        </ModalFooter>
+      </Modal>
+    </span>
+  )
 }
 
-class ModalBadge extends Component {
-  render() {
-    const { expand_text, expand_class, children, type } = this.props
-    const id = uniqueID("collapsable-badge-id-")
-    return (
-      <span>
-        <Button className={type + " " + type + "-" + expand_class} href="#" id={id} role="button">
-          {expand_text}
-        </Button>
+const ModalBadge = (props) => {
+  const { expand_text, expand_class, children, type } = props
+  const id = uniqueID("collapsable-badge-id-")
+  return (
+    <span>
+      <Button className={type + " " + type + "-" + expand_class} href="#" id={id} role="button">
+        {expand_text}
+      </Button>
 
-        <UncontrolledCollapse toggler={"#" + id} className="actions">
-          <Card>
-            <CardBody>{children}</CardBody>
-          </Card>
-        </UncontrolledCollapse>
-      </span>
-    )
-  }
+      <UncontrolledCollapse toggler={"#" + id} className="actions">
+        <Card>
+          <CardBody>{children}</CardBody>
+        </Card>
+      </UncontrolledCollapse>
+    </span>
+  )
 }
 
 CollapsableBadge.defaultProps = {
@@ -120,16 +94,14 @@ ModalBadge.defaultProps = {
   expand_class: "primary",
 }
 
-class Toggler extends Component {
-  render() {
-    const { id, text, color } = this.props
-    const classes = "btn btn-sm float-right btn-" + color
-    return (
-      <button className={classes} href="#" id={id}>
-        {text} <i class="fas fa-compass"></i>
-      </button>
-    )
-  }
+const Toggler = (props) => {
+  const { id, text, color } = props
+  const classes = "btn btn-sm float-right btn-" + color
+  return (
+    <button className={classes} href="#" id={id}>
+      {text} <i class="fas fa-compass"></i>
+    </button>
+  )
 }
 
 export { CollapsableCard, CollapsableBadge, ModalBadge }

