From 79f1395861a400b394a293957535db2dc50b59af Mon Sep 17 00:00:00 2001
From: manisha <manisha_kanyal.scsebtech@galgotiasuniversity.edu.in>
Date: Jun 21 2021 12:26:58 +0000
Subject: stepped wizard implementation


---

diff --git a/package.json b/package.json
index b9809f4..438f2b2 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
     "react-redux": "^7.2.1",
     "react-router-dom": "^5.2.0",
     "react-scripts": "^3.3.0",
+    "react-step-wizard": "^5.3.6",
     "reactstrap": "^6.5.0",
     "redux": "^4.0.5",
     "redux-logger": "^3.0.6",
diff --git a/src/App.js b/src/App.js
index b782aa0..2858284 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,28 +1,56 @@
-import React, { Component } from 'react';
-
-import { Route, Switch } from 'react-router';
-import { BrowserRouter } from 'react-router-dom'
-
-import Wizard from './wizard/Wizard';
-import LandingPage from './landingpage/LandingPage';
-import NotFound from './NotFound';
+import React, { Component } from "react"
 
+import { Route, Switch } from "react-router"
+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}>
-        <div>
-          <Switch>
-            <Route path="/" exact component={LandingPage} />
-            <Route path="/wizard" component={Wizard} />
-            <Route path="/landingpage" component={LandingPage} />
-            <Route component={NotFound} />
-          </Switch>
-        </div>
+        <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"
+            render={(props) => {
+              return <Wizard step="step2" {...props} />
+            }}
+          />
+
+          <Route
+            path="/wizard"
+            render={(props) => {
+              return <Wizard step="step1" {...props} />
+            }}
+          />
+          <Route component={NotFound} />
+        </Switch>
       </BrowserRouter>
-    );
+    )
   }
 }
 
-export default App;
+export default App
diff --git a/src/index.css b/src/index.css
index 42b981d..f92ce94 100644
--- a/src/index.css
+++ b/src/index.css
@@ -17,7 +17,6 @@ body {
   padding: 0;
   background-color: #fff;
   padding-bottom: 10rem;
-  background-color: #fff;
 }
 
 code {
@@ -57,6 +56,7 @@ h1 {
 
 .padded {
   padding-top: 0.5em;
+  font-weight: normal;
 }
 
 .timeline {
@@ -180,3 +180,48 @@ ol.steps > li {
 .title {
   font-size: 1.2em;
 }
+
+.clickable {
+  cursor: pointer;
+}
+
+.card-selected {
+  background-image: linear-gradient(to bottom, #eee 0%, rgb(241, 240, 240) 100%);
+  border: #c8c9ca solid 2px;
+}
+.wrapper {
+  display: flex;
+  align-items: center;
+  -webkit-justify-content: center;
+  justify-content: center;
+}
+.wizard {
+  position: relative;
+  padding: 40px 3px;
+  width: 100%;
+}
+.actions {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+
+.card-container {
+  min-height: 5rem;
+  margin-bottom: 10px;
+  margin-top: 10px;
+}
+.disabled {
+  pointer-events: none;
+  cursor: default;
+  color: rgb(104, 102, 102);
+}
+
+.enable {
+  cursor: pointer;
+  color: #3864a3;
+  text-decoration: none;
+  background-color: transparent;
+}
+.enable:hover {
+  text-decoration: underline;
+}
diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js
index d02b00c..b406f41 100644
--- a/src/landingpage/LandingPage.js
+++ b/src/landingpage/LandingPage.js
@@ -18,7 +18,6 @@ import Minutes from "./Minutes"
 import * as R from "ramda"
 import { connect } from "react-redux"
 import { loadData } from "../actions/reduxActions"
-
 import Cookies from "universal-cookie"
 
 class LandingPage extends Component {
diff --git a/src/wizard/Actions.js b/src/wizard/Actions.js
deleted file mode 100644
index fe9864b..0000000
--- a/src/wizard/Actions.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React, { Component } from "react"
-
-import Easyfix from "./Easyfix"
-import FedoraManualTesting from "./FedoraManualTesting"
-import FedoraEasyKarma from "./FedoraEasyKarma"
-import * as R from 'ramda'
-
-export class Actions extends Component {
-  render() {
-    var outdata = []
-    const grouped = R.groupBy((action) => action.provider, this.props.data)
-
-     const processData = (data, firstLevelGroupKey, secondLevelGroupKey) => {
-      const getProcessedData = R.pipe(
-        R.groupBy((a) => a.extra_data[firstLevelGroupKey]),
-        R.map((v) => R.groupBy((a) => a.extra_data[secondLevelGroupKey], v))
-      );
-      return getProcessedData(data)
-     }
- 
-    const manualTestingData = processData(grouped["fedora_manual_testing"] || [], 'testtype', 'section')
-    const easyfixTestingData = processData(grouped["easyfix"] || [], 'repo_org', 'repo_name')
-
-    outdata.push(
-      <FedoraManualTesting
-        data={manualTestingData}
-        key="fmtl"
-      />
-    )
-    outdata.push(
-      <Easyfix
-        data={easyfixTestingData}
-        key="easyfix"
-      />
-    )
-    outdata.push(<FedoraEasyKarma data={grouped["fedora_easy_karma"]} key="karma" />)
-
-    return <div>{outdata}</div>
-  }
-}
-
-export default Actions
diff --git a/src/wizard/Easyfix.js b/src/wizard/Easyfix.js
index ebccbfc..71ac755 100644
--- a/src/wizard/Easyfix.js
+++ b/src/wizard/Easyfix.js
@@ -1,15 +1,17 @@
 import React, { Component } from "react"
 import { CollapsableCard } from "./components"
+import { Col } from "reactstrap"
 
 export default class Easyfix extends Component {
   render() {
-    console.log(this.props.data)
     return (
-      <div>
-        {Object.keys(this.props.data).map((k) => {
-          return <EasyfixSection title={k} data={this.props.data[k]} key={"section" + k} />
-        })}
-      </div>
+      <>
+        {Object.keys(this.props.data).map((k) => (
+          <Col sm="6">
+            <EasyfixSection title={k} data={this.props.data[k]} key={"section" + k} />
+          </Col>
+        ))}
+      </>
     )
   }
 }
@@ -28,7 +30,7 @@ class EasyfixSection extends Component {
         )
 
         return (
-          <CollapsableCard key={k} title={title} expand_class="primary" expand_text="Show me!">
+          <CollapsableCard key={k} title={title} expand_class="primary" expand_text="See!">
             <EasyfixLinksList data={this.props.data[k]} />
           </CollapsableCard>
         )
@@ -64,7 +66,7 @@ class EasyfixSection extends Component {
       ))
 
       return (
-        <CollapsableCard key={title} title={title} expand_class="primary" expand_text="Show me!">
+        <CollapsableCard key={title} title={title} expand_class="primary" expand_text="See!">
           {links}
         </CollapsableCard>
       )
diff --git a/src/wizard/FedoraEasyKarma.js b/src/wizard/FedoraEasyKarma.js
index d4e6be6..830cce5 100644
--- a/src/wizard/FedoraEasyKarma.js
+++ b/src/wizard/FedoraEasyKarma.js
@@ -1,5 +1,5 @@
 import React, { Component } from "react"
-import { CollapsableBadge } from "./components"
+import { CollapsableBadge, ModalBadge } from "./components"
 
 export default class FedoraEasyKarmaItemsList extends Component {
   render() {
@@ -70,7 +70,7 @@ export default class FedoraEasyKarmaItemsList extends Component {
                 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.{" "}
-                <CollapsableBadge expand_text="Want something a bit nicer?">
+                <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.
@@ -82,7 +82,7 @@ export default class FedoraEasyKarmaItemsList extends Component {
                   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.
-                </CollapsableBadge>
+                </ModalBadge>
               </CollapsableBadge>
             </li>
             <li>
@@ -94,7 +94,7 @@ export default class FedoraEasyKarmaItemsList extends Component {
                 <br />
                 You are then presented with the relevant updates one-by-one, to submit Karma and a
                 comment.{" "}
-                <CollapsableBadge expand_text="Not sure what Karma means?">
+                <ModalBadge expand_text="Not sure what Karma means?">
                   <ol>
                     <li>
                       Enter <code>1</code> to mark positive karma (the update works just fine, as
@@ -123,7 +123,7 @@ export default class FedoraEasyKarmaItemsList extends Component {
                       it in the comment.
                     </li>
                   </ol>
-                </CollapsableBadge>
+                </ModalBadge>
               </CollapsableBadge>
             </li>
             <li>
diff --git a/src/wizard/FedoraManualTesting.js b/src/wizard/FedoraManualTesting.js
index 21fbc21..ce47599 100644
--- a/src/wizard/FedoraManualTesting.js
+++ b/src/wizard/FedoraManualTesting.js
@@ -1,6 +1,6 @@
 import React, { Component } from "react"
 import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap"
-import { CollapsableCard, CollapsableBadge } from "./components"
+import { CollapsableCard, ModalBadge } from "./components"
 
 export default class FedoraManualTesting extends Component {
   render() {
@@ -25,7 +25,7 @@ class FedoraManualTestingItemsListSub2 extends Component {
   }
 }
 
-class FedoraManualTestingItemsListSub1 extends Component {
+export class FedoraManualTestingItemsListSub1 extends Component {
   render() {
     var subsections = Object.keys(this.props.data).map((k) => (
       <li key={"li" + k}>
@@ -106,14 +106,14 @@ class FedoraManualTestingItemsListSub1 extends Component {
     }
 
     return (
-      <CollapsableCard title={l1} expand_text="Show me!" expand_class="primary">
+      <CollapsableCard title={l1} expand_text="See" expand_class="primary">
         {subsections}
       </CollapsableCard>
     )
   }
 }
 
-class FedoraManualTestingItem extends Component {
+export class FedoraManualTestingItem extends Component {
   render() {
     const extra_data = this.props.data.extra_data
 
@@ -167,7 +167,7 @@ class FedoraManualTestingItem extends Component {
             <a target="_blank" rel="noopener noreferrer" href={matrix_url}>
               Tescase matrix
             </a>{" "}
-            <CollapsableBadge expand_text="Not sure what that means?">
+            <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
@@ -181,7 +181,7 @@ class FedoraManualTestingItem extends Component {
                   results.
                 </li>
               </ul>
-            </CollapsableBadge>
+            </ModalBadge>
           </li>
 
           <li>
@@ -190,7 +190,7 @@ class FedoraManualTestingItem extends Component {
               Testcase
             </a>{" "}
             briefly, just to have a general idea of what you will be doing.{" "}
-            <CollapsableBadge expand_text="Not making much sense?">
+            <ModalBadge expand_text="Not making much sense?">
               The testcases are generally split into four sections:
               <ul>
                 <li>
@@ -210,7 +210,7 @@ class FedoraManualTestingItem extends Component {
                   order to decide whether it Passed of Failed
                 </li>
               </ul>
-            </CollapsableBadge>
+            </ModalBadge>
           </li>
 
           <li>
@@ -222,7 +222,7 @@ class FedoraManualTestingItem extends Component {
               here
             </a>
             .{" "}
-            <CollapsableBadge expand_text="Not sure how?">
+            <ModalBadge expand_text="Not sure how?">
               <ul>
                 <li>
                   Most of the time Workstation Live, or Server DVD are fine, but sometimes there
@@ -230,7 +230,7 @@ class FedoraManualTestingItem extends Component {
                 </li>
                 <li>
                   Make sure to read about identifying the environment above.{" "}
-                  <CollapsableBadge expand_text="Show me!">
+                  <ModalBadge expand_text="See">
                     <ul>
                       <li>
                         Have a look at the matrix. The rows are the testcases, and the columns are
@@ -245,10 +245,10 @@ class FedoraManualTestingItem extends Component {
                         missing results.
                       </li>
                     </ul>
-                  </CollapsableBadge>
+                  </ModalBadge>
                 </li>
               </ul>
-            </CollapsableBadge>
+            </ModalBadge>
           </li>
 
           <li>
@@ -257,11 +257,11 @@ class FedoraManualTestingItem extends Component {
               Testcase
             </a>{" "}
             thoroughly, to be sure you know what to do.{" "}
-            <CollapsableBadge expand_text="Feeling a bit lost?">
+            <ModalBadge expand_text="Feeling a bit lost?">
               <ul>
                 <li>
                   The testcase structure is not making sense?{" "}
-                  <CollapsableBadge expand_text="Click here">
+                  <ModalBadge expand_text="Click here">
                     The testcases are generally split into four sections:
                     <ul>
                       <li>
@@ -281,12 +281,12 @@ class FedoraManualTestingItem extends Component {
                         testing in order to decide whether it Passed of Failed
                       </li>
                     </ul>
-                  </CollapsableBadge>
+                  </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{" "}
-                  <CollapsableBadge expand_text="Don&#39;t have an IRC client?">
+                  <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"
@@ -296,15 +296,15 @@ class FedoraManualTestingItem extends Component {
                     </a>{" "}
                     just enter a Nickname of your choice, #fedora-qa (including the hash sign) in
                     the Channels field, and click Connect.
-                  </CollapsableBadge>
+                  </ModalBadge>
                 </li>
               </ul>
-            </CollapsableBadge>
+            </ModalBadge>
           </li>
 
           <li>Get your hands dirty, and test the hell out of it!</li>
           <li>
-            <CollapsableBadge expand_class="success" expand_text="Everything went well" type="btn">
+            <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}>
@@ -313,9 +313,9 @@ class FedoraManualTestingItem extends Component {
               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.
-            </CollapsableBadge>
+            </ModalBadge>
 
-            <CollapsableBadge expand_class="danger" expand_text="I found a bug!" type="btn">
+            <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
@@ -341,11 +341,11 @@ class FedoraManualTestingItem extends Component {
                 <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{" "}
-                  <CollapsableBadge expand_text="Don&#39;t have an IRC client?">
+                  <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.
-                  </CollapsableBadge>
+                  </ModalBadge>
                 </li>
               </ul>
               Once you get the Bug reported, make sure to also submit the result into the testing
@@ -357,7 +357,7 @@ class FedoraManualTestingItem extends Component {
               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.
-            </CollapsableBadge>
+            </ModalBadge>
           </li>
         </ol>
       </ModalInfo>
diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js
index 86a8227..5d5b90b 100644
--- a/src/wizard/Wizard.js
+++ b/src/wizard/Wizard.js
@@ -1,66 +1,52 @@
-import React, { Component } from "react"
-import WizardForm from "./WizardForm"
+import React, { useEffect } from "react"
 import Layout from "../layout/Layout"
-import Actions from "./Actions"
-import { Container, Row } from "reactstrap"
+import { Col, Container, Row } from "reactstrap"
 
-import { connect } from "react-redux"
+import { useDispatch, useSelector, shallowEqual } from "react-redux"
 import { loadWizardData } from "../actions/reduxActions"
+import WizardStepper from "./WizardStepper"
+import { useParams } from "react-router"
 
-class Wizard extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      actions: [],
-    }
-    this.getData = this.getData.bind(this)
-  }
+import WizardNavigation from "./WizardNavigation"
 
-  getData() {
-    this.props.dispatch(loadWizardData())
-  }
+const Wizard = (props) => {
+  const { step } = props
+  const query = useParams()
+  const selectAction = (state) => state.wizard.api_call_status
 
-  componentDidMount() {
-    this.getData()
-  }
+  const api_call_status = useSelector(selectAction, shallowEqual)
 
-  show_actions(actions) {
-    this.setState({ actions })
-  }
+  const dispatch = useDispatch()
 
-  render() {
-    return (
-      <Layout apiCallStatus={this.props.api_call_status}>
-        <div className="bluebox">
-          <Container>
-            <WizardForm
-              show_actions={this.show_actions.bind(this)}
-              actions={this.props.all_actions}
-              providers={this.props.providers}
-            />
-            <h1>Nothing sparked joy?</h1>
-            <div>
-              None of the above looks interesting to you? We'd be happy if you looked around at{" "}
-              <a href="https://whatcanidoforfedora.org/">https://whatcanidoforfedora.org/</a>!
-            </div>
-          </Container>
-        </div>
-        <Container>
-          <Row>
-            <div className="col-md-12">
-              <Actions data={this.state.actions} />
-            </div>
-          </Row>
-        </Container>
-      </Layout>
-    )
+  const getData = () => {
+    dispatch(loadWizardData())
   }
-}
 
-const mapStateToProps = (state) => {
-  return {
-    ...state.wizard,
-  }
+  useEffect(() => {
+    getData()
+  }, [])
+
+  return (
+    <Layout apiCallStatus={api_call_status}>
+      <Container>
+        <Row className="justify-content-center align-items-center">
+          <div className="wizard">
+            <WizardNavigation step={step} />
+            <WizardStepper step={step} />
+
+            {query.issues || query.action || query.provider === "fedora_easy_karma" ? (
+              <Col md="12">
+                <h5 className="padded text-center">
+                  None of the above looks interesting to you? We'd be happy if you looked around at{" "}
+                  <a href="https://whatcanidoforfedora.org/">https://whatcanidoforfedora.org/</a>!
+                </h5>
+              </Col>
+            ) : null}
+          </div>
+        </Row>
+      </Container>
+    </Layout>
+  )
 }
 
-export default connect(mapStateToProps)(Wizard)
+export default Wizard
diff --git a/src/wizard/WizardForm.js b/src/wizard/WizardForm.js
deleted file mode 100644
index ec35641..0000000
--- a/src/wizard/WizardForm.js
+++ /dev/null
@@ -1,144 +0,0 @@
-import React, { Component } from "react"
-import { Row, Button } from "reactstrap"
-import * as R from "ramda"
-
-const durationString = {
-  3: "Few hours",
-  72: "Several days",
-}
-
-class WizardForm extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      selected_provider: "",
-      selected_provider_tags: [],
-    }
-  }
-
-  provider_selected(provider) {
-    const getUniqueTags = R.pipe(
-      R.map((action) => action.tags),
-      R.flatten,
-      R.uniq
-    )
-
-    const tags = getUniqueTags(this.props.actions[provider.provider])
-
-    this.props.show_actions([])
-    this.setState(
-      {
-        selected_provider: provider,
-        selected_provider_tags: tags,
-      },
-      () => {
-        if (!provider.tags) this.props.show_actions(this.props.actions[provider.provider])
-      }
-    )
-  }
-
-  tag_selected(tag) {
-    const actions = R.filter(
-      (a) => a.tags.includes(tag),
-      this.props.actions[this.state.selected_provider.provider]
-    )
-    this.props.show_actions(actions)
-  }
-
-  render() {
-    const providers = [3, 72].map((duration) => {
-      const duration_providers = this.props.providers
-        .filter((p) => p.duration === duration)
-        .map((p) => {
-          const btncolor =
-            this.state.selected_provider.provider === p.provider ? "secondary" : "primary"
-          return (
-            <div className="card" key={"provider_card" + p.provider}>
-              <div className="card-body">
-                <Row key={p.provider}>
-                  <div className="col-md-10">
-                    <strong>
-                      {p.scope} - {p.name}
-                    </strong>
-                    <br />
-                    {p.description}
-                  </div>
-                  <div className="col-md-2">
-                    <Button
-                      className="btn-sm btn-block btn-wrap-text float-right"
-                      color={btncolor}
-                      onClick={(event) => this.provider_selected(p)}>
-                      Tell me more!
-                    </Button>
-                  </div>
-                </Row>
-              </div>
-            </div>
-          )
-        })
-
-      return (
-        <div key={duration}>
-          <h1 className="padded">{durationString[duration]}</h1>
-          {duration_providers}
-        </div>
-      )
-    })
-
-    const tag_selector =
-      this.state.selected_provider === "" || !this.state.selected_provider.tags ? null : (
-        <Row>
-          <div className="col-md-12">
-            <h1 className="padded">Make your choice!</h1>
-            <Tags
-              key={this.state.selected_provider.provider}
-              data={this.state.selected_provider_tags.sort()}
-              handler={this.tag_selected.bind(this)}
-            />
-          </div>
-        </Row>
-      )
-
-    return (
-      <div>
-        <Row>
-          <div className="col-md-12">{providers}</div>
-        </Row>
-        {tag_selector}
-      </div>
-    )
-  }
-}
-
-class Tags extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      selected_button: undefined,
-    }
-  }
-
-  selected(t) {
-    this.props.handler(t)
-    this.setState({ selected_button: t })
-  }
-
-  is_selected(t) {
-    return t === this.state.selected_button ? "selected" : "primary"
-  }
-
-  render() {
-    var x = this.props.data.map((tag) => (
-      <Button
-        onClick={() => this.selected(tag)}
-        className="btn-sm btn-tag"
-        color={this.is_selected(tag)}
-        key={tag}>
-        {tag}
-      </Button>
-    ))
-    return <div>{x}</div>
-  }
-}
-
-export default WizardForm
diff --git a/src/wizard/WizardNavigation.js b/src/wizard/WizardNavigation.js
new file mode 100644
index 0000000..2ff4d0f
--- /dev/null
+++ b/src/wizard/WizardNavigation.js
@@ -0,0 +1,100 @@
+import React from "react"
+import { useParams } from "react-router"
+import { Breadcrumb, BreadcrumbItem } from "reactstrap"
+import { Link } from "react-router-dom"
+import { useSelector, shallowEqual } from "react-redux"
+import * as R from "ramda"
+
+function WizardNavigation(props) {
+  const query = useParams()
+
+  const { step } = props
+
+  const selectAction = (state) => state.wizard.all_actions
+  const actions = useSelector(selectAction, shallowEqual)
+  const grouped = R.groupBy((action) => action.provider, actions["easyfix"])
+
+  const getTags = () => {
+    const getUniqueTags = R.pipe(
+      R.map((action) => action.tags),
+      R.flatten,
+      R.uniq
+    )
+    const tags = getUniqueTags(grouped["easyfix"])
+    return tags
+  }
+
+  const selectNavigation = (location) => {
+    switch (location) {
+      case "Start":
+        return `/wizard/`
+      case "Duration":
+        return `/wizard/${query.duration}`
+      case "Provider":
+        return `/wizard/${query.duration}/${query.provider}`
+
+      case "Actions":
+        return `/wizard/${query.duration}/${query.provider}/${query.action}`
+
+      case "Issues":
+        return `/wizard/${query.duration}/${query.provider}/${query.action}`
+
+      default:
+        return `/wizard`
+    }
+  }
+
+  const createBreadcrumbItem = (to, classname, text) => {
+    return (
+      <BreadcrumbItem key={text}>
+        <Link to={selectNavigation(to)} className={classname}>
+          {text}
+        </Link>
+      </BreadcrumbItem>
+    )
+  }
+
+  const navigators = [
+    createBreadcrumbItem("Start", step.slice(-1) > "1" ? "enable" : "disabled", "Start"),
+    createBreadcrumbItem(
+      "Duration",
+      step.slice(-1) > "2" ? "enable" : "disabled",
+      query.duration === "few_hours" ? "Few Hours" : "Several Days"
+    ),
+    createBreadcrumbItem(
+      "Provider",
+      step.slice(-1) > "3" ? "enable" : "disabled",
+      query.provider === "fedora_manual_testing"
+        ? "Fedora Manual Testing"
+        : query.provider === "easyfix"
+        ? "Easyfix"
+        : "Bodhi Karma"
+    ),
+    createBreadcrumbItem(
+      "Actions",
+      step.slice(-1) > "4" ? "enable" : "disabled",
+      query.action
+        ? getTags().filter((a) => a.toLowerCase() === decodeURIComponent(query.action))[0] ||
+            query.action.charAt(0).toUpperCase() + query.action.slice(1)
+        : null
+    ),
+    createBreadcrumbItem(
+      "Issues",
+      step.slice(-1) > "5" ? "enable" : "disabled",
+      decodeURIComponent(query.issues)
+    ),
+  ]
+
+  return (
+    <div>
+      <Breadcrumb>
+        <li>
+          <i className="fas fa-angle-double-right"></i> &nbsp;
+        </li>
+        {navigators.slice(0, Number(step.slice(-1))).map((comp) => comp)}
+      </Breadcrumb>
+    </div>
+  )
+}
+
+export default WizardNavigation
diff --git a/src/wizard/WizardStepper.js b/src/wizard/WizardStepper.js
new file mode 100644
index 0000000..d802484
--- /dev/null
+++ b/src/wizard/WizardStepper.js
@@ -0,0 +1,27 @@
+import React from "react"
+import { Container } from "reactstrap"
+import Step1 from "./step/Step1"
+import Step2 from "./step/Step2"
+import Step3 from "./step/Step3"
+import Step4 from "./step/Step4"
+import Step5 from "./step/Step5"
+import { useParams } from "react-router-dom"
+
+const WizardStepper = (props) => {
+  const { step } = props
+  const query = useParams()
+
+  return (
+    <Container>
+      <div className="wizard">
+        {step === "step1" && <Step1 step={step} query={query} {...props} />}
+        {step === "step2" && <Step2 step={step} query={query} {...props} />}
+        {step === "step3" && <Step3 step={step} query={query} {...props} />}
+        {step === "step4" && <Step4 step={step} query={query} {...props} />}
+        {step === "step5" && <Step5 step={step} query={query} {...props} />}
+      </div>
+    </Container>
+  )
+}
+
+export default WizardStepper
diff --git a/src/wizard/components.js b/src/wizard/components.js
index 4b2c8f3..85b7471 100644
--- a/src/wizard/components.js
+++ b/src/wizard/components.js
@@ -1,8 +1,33 @@
 import React, { Component } from "react"
-import { Card, CardHeader, CardBody, UncontrolledCollapse, Row } from "reactstrap"
+import {
+  Card,
+  CardHeader,
+  CardBody,
+  UncontrolledCollapse,
+  Row,
+  Modal,
+  ModalBody,
+  ModalFooter,
+  Button,
+} 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-")
@@ -10,8 +35,8 @@ class CollapsableCard extends Component {
       <Card>
         <CardHeader>
           <Row>
-            <div className="col-md-11">{title}</div>
-            <div className="col-md-1">
+            <div className="col-sm-10">{title}</div>
+            <div className="col-sm-2">
               <Toggler id={id} color={expand_class} text={expand_text} />
             </div>
           </Row>
@@ -25,15 +50,61 @@ class CollapsableCard extends Component {
 }
 
 class CollapsableBadge 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 { 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>
+    )
+  }
+}
+
+class ModalBadge extends Component {
   render() {
     const { expand_text, expand_class, children, type } = this.props
     const id = uniqueID("collapsable-badge-id-")
     return (
       <span>
-        <a class={type + " " + type + "-" + expand_class} href="#" id={id} role="button">
+        <Button className={type + " " + type + "-" + expand_class} href="#" id={id} role="button">
           {expand_text}
-        </a>
-        <UncontrolledCollapse toggler={"#" + id}>{children}</UncontrolledCollapse>
+        </Button>
+
+        <UncontrolledCollapse toggler={"#" + id} className="actions">
+          <Card>
+            <CardBody>{children}</CardBody>
+          </Card>
+        </UncontrolledCollapse>
       </span>
     )
   }
@@ -44,16 +115,21 @@ CollapsableBadge.defaultProps = {
   expand_class: "primary",
 }
 
+ModalBadge.defaultProps = {
+  type: "badge",
+  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}
+        {text} <i class="fas fa-compass"></i>
       </button>
     )
   }
 }
 
-export { CollapsableCard, CollapsableBadge }
+export { CollapsableCard, CollapsableBadge, ModalBadge }
diff --git a/src/wizard/step/Step1.js b/src/wizard/step/Step1.js
new file mode 100644
index 0000000..d72cd0f
--- /dev/null
+++ b/src/wizard/step/Step1.js
@@ -0,0 +1,51 @@
+import React, { useState } from "react"
+import { Link, useHistory } from "react-router-dom"
+import { Card, CardText, Button, Col, Row } from "reactstrap"
+
+const Step1 = (props) => {
+  const [selectedItem, setItem] = useState()
+  const history = useHistory()
+  const handleStep = (option) => {
+    setItem(option)
+    history.push(`/wizard/${option}`)
+  }
+
+  return (
+    <Row className="padded">
+      <Col sm="6">
+        <Card
+          className={
+            "clickable text-center" + (selectedItem === "Several_days" ? " card-selected" : "")
+          }
+          body
+          type="btn"
+          onClick={() => {
+            handleStep("several_days")
+          }}>
+          <h1 className="padded">
+            Several Days <i className="fas fa-calendar-week"></i>
+          </h1>
+          <CardText>Task that can take up to Several Days </CardText>
+        </Card>
+      </Col>
+      <Col sm="6">
+        <Card
+          className={
+            "clickable text-center" + (selectedItem === "few_hours" ? " card-selected" : "")
+          }
+          body
+          type="btn"
+          onClick={() => {
+            handleStep("few_hours")
+          }}>
+          <h1 className="padded">
+            Few Hours <i className="fas fa-calendar-day"></i>
+          </h1>
+          <CardText>Task that can take up to Few Hours </CardText>
+        </Card>
+      </Col>
+    </Row>
+  )
+}
+
+export default Step1
diff --git a/src/wizard/step/Step2.js b/src/wizard/step/Step2.js
new file mode 100644
index 0000000..2ae97ff
--- /dev/null
+++ b/src/wizard/step/Step2.js
@@ -0,0 +1,88 @@
+import React, { useState } from "react"
+import { shallowEqual, useSelector } from "react-redux"
+import { Card, CardBody, CardTitle, CardText, Row, Col } from "reactstrap"
+import { useHistory } from "react-router-dom"
+
+const Step2 = (props) => {
+  const { query } = props
+
+  const [selectedItem, setItem] = useState()
+  const history = useHistory()
+
+  const handleStep = (option) => {
+    setItem(option)
+    history.push(`/wizard/${query.duration}/${option}`)
+  }
+
+  const selectProvider = (state) => state.wizard.providers
+
+  const providers = useSelector(selectProvider, shallowEqual)
+
+  const fewHours = providers.filter((provider) => provider.duration === 3)
+  const severalDays = providers.filter((provider) => provider.duration === 72)
+
+  const getIcon = (type) => {
+    switch (type) {
+      case "fedora_manual_testing":
+        return <i className="fas fa-user-check"></i>
+      case "easy_fix":
+        return <i className="fas fa-magic"></i>
+      default:
+        return <i className="fab fa-fedora"></i>
+    }
+  }
+
+  return (
+    <Row className="justify-content-center">
+      {query.duration === "several_days" && (
+        <>
+          {severalDays.map((item) => (
+            <Col sm="6" key={item.provider}>
+              <Card
+                className={
+                  "clickable text-center" +
+                  (selectedItem === item.provider ? " card-selected" : "")
+                }
+                onClick={() => {
+                  handleStep(item.provider)
+                }}>
+                <CardBody>
+                  <CardTitle tag="h4">
+                    {item.name} {getIcon(item.provider)}
+                  </CardTitle>
+                  <CardText>{item.description}</CardText>
+                </CardBody>
+              </Card>
+            </Col>
+          ))}
+        </>
+      )}
+
+      {query.duration === "few_hours" && (
+        <>
+          {fewHours.map((item) => (
+            <Col sm="6" key={item.provider}>
+              <Card
+                className={
+                  "clickable text-center" +
+                  (selectedItem === item.provider ? " card-selected" : "")
+                }
+                onClick={() => {
+                  handleStep(item.provider)
+                }}>
+                <CardBody>
+                  <CardTitle tag="h4">
+                    {item.name} {getIcon(item.provider)}
+                  </CardTitle>
+                  <CardText>{item.description}</CardText>
+                </CardBody>
+              </Card>
+            </Col>
+          ))}
+        </>
+      )}
+    </Row>
+  )
+}
+
+export default Step2
diff --git a/src/wizard/step/Step3.js b/src/wizard/step/Step3.js
new file mode 100644
index 0000000..7ca64bb
--- /dev/null
+++ b/src/wizard/step/Step3.js
@@ -0,0 +1,205 @@
+import React, { useState } from "react"
+import { shallowEqual, useSelector } from "react-redux"
+import { Card, CardBody, CardTitle, Col, Row, CardHeader } from "reactstrap"
+
+import FedoraEasyKarma from "../FedoraEasyKarma"
+import * as R from "ramda"
+import { useHistory } from "react-router"
+
+const Step3 = (props) => {
+  const { query } = props
+
+  const [selectedItem, setItem] = useState()
+  const history = useHistory()
+
+  const handleStep = (option) => {
+    setItem(option)
+    history.push(
+      `/wizard/${query.duration}/${query.provider}/${encodeURIComponent(option.toLowerCase())}`
+    )
+  }
+
+  const selectAction = (state) => state.wizard.all_actions
+
+  const actions = useSelector(selectAction, shallowEqual)
+  const grouped = R.groupBy((action) => action.provider, actions[query.provider])
+
+  const getData = () => {
+    const getUniqueTags = R.pipe(
+      R.map((action) => action.tags),
+      R.flatten,
+      R.uniq
+    )
+    const tags = getUniqueTags(grouped["easyfix"])
+    return tags
+  }
+
+  const getData2 = () => {
+    const getUniqueTags = R.pipe(
+      R.map((action) => action.extra_data.testtype),
+      R.flatten,
+      R.uniq
+    )
+    const tags = getUniqueTags(grouped["fedora_manual_testing"])
+    return tags
+  }
+
+  const getLanguageIcon = (lang) => {
+    switch (lang) {
+      case "Python":
+        return <i className="fab fa-python"></i>
+      case "JavaScript":
+        return <i className="fab fa-js-square"></i>
+      case "HTML":
+        return <i className="fab fa-html5"></i>
+      case "PHP":
+        return <i className="fab fa-php"></i>
+      default:
+        return <i className="fas fa-terminal"></i>
+    }
+  }
+
+  const getIcontestype = (item) => {
+    switch (item) {
+      case "Cloud":
+        return <i className="fas fa-cloud"></i>
+      case "Installation":
+        return <i className="fas fa-download"></i>
+      case "Desktop":
+        return <i className="fas fa-desktop"></i>
+      case "Server":
+        return <i className="fas fa-server"></i>
+      default:
+        return <i className="fab fa-fedora"></i>
+    }
+  }
+
+  const getTesttype = (testtype) => {
+    switch (testtype) {
+      case "Installation":
+        return (
+          <div className="text-left">
+            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>
+        )
+
+      case "Desktop":
+        return (
+          <div className="text-left">
+            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>
+        )
+
+      case "Base":
+        return (
+          <div className="text-left">
+            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>
+        )
+
+      case "Server":
+        return (
+          <div className="text-left">
+            The <strong>Server</strong> testcases usually require multiple machines to test the
+            server-client behaviour, and might feel a bit advanced.
+          </div>
+        )
+
+      case "Cloud":
+        return (
+          <div className="text-left">
+            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>
+        )
+
+      default:
+        break
+    }
+  }
+
+  return (
+    <Row>
+      {query.provider === "fedora_manual_testing" && (
+        <>
+          {getData2().map((item) => (
+            <Col sm="6" className="card-container" key={item.toString()}>
+              <Card
+                onClick={() => {
+                  handleStep(item)
+                }}
+                className={
+                  "clickable text-center" + (selectedItem === item ? " card-selected" : "")
+                }>
+                <CardHeader className="title">
+                  {item} {getIcontestype(item)}{" "}
+                </CardHeader>
+                <CardBody>{getTesttype(item)}</CardBody>
+              </Card>
+            </Col>
+          ))}
+        </>
+      )}
+
+      {query.provider === "fedora_easy_karma" && (
+        <Col sm="12">
+          <Card>
+            <CardBody>
+              <FedoraEasyKarma data={grouped["fedora_easy_karma"]} key="karma" />
+            </CardBody>
+          </Card>
+        </Col>
+      )}
+      {query.provider === "easyfix" && (
+        <>
+          {getData().map((lang) => (
+            <Col sm="6" key={lang.toString()}>
+              <Card
+                className={
+                  "clickable text-center" + (selectedItem === lang ? " card-selected" : "")
+                }
+                onClick={() => {
+                  handleStep(lang)
+                }}>
+                <CardBody>
+                  <CardTitle tag="h4">
+                    {lang} &nbsp; {getLanguageIcon(lang)}{" "}
+                  </CardTitle>
+                </CardBody>
+              </Card>
+            </Col>
+          ))}
+        </>
+      )}
+    </Row>
+  )
+}
+
+export default Step3
diff --git a/src/wizard/step/Step4.js b/src/wizard/step/Step4.js
new file mode 100644
index 0000000..6640fcb
--- /dev/null
+++ b/src/wizard/step/Step4.js
@@ -0,0 +1,92 @@
+import React, { useState } from "react"
+import { Row, Col, Card, CardBody, CardHeader } from "reactstrap"
+import { shallowEqual, useSelector } from "react-redux"
+import * as R from "ramda"
+import { FedoraManualTestingItem } from "../FedoraManualTesting"
+import { useHistory } from "react-router-dom"
+const Step4 = (props) => {
+  const { query } = props
+
+  const [selectItem, setselectItem] = useState()
+
+  const history = useHistory()
+
+  const handleChange = (option) => {
+    history.push(
+      `/wizard/${query.duration}/${query.provider}/${query.action}/${encodeURIComponent(option)}`
+    )
+    setselectItem(option)
+  }
+
+  const selectAction = (state) => state.wizard.all_actions
+
+  const actions = useSelector(selectAction, shallowEqual)
+  const grouped = R.groupBy((action) => action.provider, actions["easyfix"])
+  const grouped2 = R.groupBy((action) => action.provider, actions["fedora_manual_testing"])
+
+  const getTags = () => {
+    const getUniqueTags = R.pipe(
+      R.map((action) => action.tags),
+      R.flatten,
+      R.uniq
+    )
+    const tags = getUniqueTags(grouped["easyfix"])
+    return tags
+  }
+
+  const getEasyfix = () => {
+    const actions = R.filter(
+      (a) =>
+        a.tags.includes(
+          getTags().filter((item) => item.toLowerCase() === decodeURIComponent(query.action))[0]
+        ),
+      grouped["easyfix"]
+    )
+    return actions
+  }
+
+  const processData = (data, firstLevelGroupKey) => {
+    const getProcessedData = R.groupBy((a) => a.extra_data[firstLevelGroupKey])
+    return getProcessedData(data)
+  }
+
+  const easyData = processData(getEasyfix() || [], "repo_fullname")
+
+  const getFedoraManualTesting = () => {
+    const actions = R.filter(
+      (a) =>
+        a.extra_data.testtype.includes(
+          query.action.charAt(0).toUpperCase() + query.action.slice(1)
+        ),
+      grouped2["fedora_manual_testing"]
+    )
+    return actions
+  }
+
+  return (
+    <Row>
+      {query.provider === "easyfix" &&
+        Object.keys(easyData).map((key) => (
+          <Col key={key} sm="6" className="card-container">
+            <Card className="clickable text-center" onClick={() => handleChange(key)}>
+              <CardHeader className="title">{key}</CardHeader>
+              <CardBody className="text-left">{easyData[key][0].extra_data.description}</CardBody>
+            </Card>
+          </Col>
+        ))}
+      {query.provider === "fedora_manual_testing" &&
+        getFedoraManualTesting().map((data, index) => (
+          <Col key={index} sm="4" md="3" className="card-container">
+            <Card>
+              <CardHeader>{data.extra_data.milestone}</CardHeader>
+              <CardBody>
+                <FedoraManualTestingItem data={data} />
+              </CardBody>
+            </Card>
+          </Col>
+        ))}
+    </Row>
+  )
+}
+
+export default Step4
diff --git a/src/wizard/step/Step5.js b/src/wizard/step/Step5.js
new file mode 100644
index 0000000..7755293
--- /dev/null
+++ b/src/wizard/step/Step5.js
@@ -0,0 +1,41 @@
+import React from "react"
+import { Row, Col, Card, CardBody, CardHeader } from "reactstrap"
+import * as R from "ramda"
+import { shallowEqual, useSelector } from "react-redux"
+
+const Step5 = (props) => {
+  const { query } = props
+
+  const selectAction = (state) => state.wizard.all_actions
+
+  const actions = useSelector(selectAction, shallowEqual)
+  const grouped = R.groupBy((action) => action.provider, actions["easyfix"])
+
+  const getIssues = () => {
+    const actions = R.filter(
+      (a) => a.extra_data.repo_fullname.includes(decodeURIComponent(query.issues)),
+      grouped["easyfix"]
+    )
+    return actions
+  }
+
+  return (
+    <Row>
+      {query.issues &&
+        getIssues().map((data) => (
+          <Col sm="4" md="3" className="card-container" key={data.extra_data.ticket_url}>
+            <Card>
+              <CardHeader>{data.extra_data.repo_name}</CardHeader>
+              <CardBody>
+                <a href={data.extra_data.ticket_url} target="_blank" rel="noopener noreferrer">
+                  {data.name}
+                </a>
+              </CardBody>
+            </Card>
+          </Col>
+        ))}
+    </Row>
+  )
+}
+
+export default Step5

