From 95ec5ba6018d6e9f03ac4fe01376edc6add26b05 Mon Sep 17 00:00:00 2001 From: Lukas Brabec Date: Jan 22 2019 14:20:51 +0000 Subject: some more polishing --- diff --git a/src/ActionItems.js b/src/ActionItems.js deleted file mode 100644 index 5a84ce7..0000000 --- a/src/ActionItems.js +++ /dev/null @@ -1,253 +0,0 @@ -import React, { Component } from 'react'; -import { FedoraManualTesting, Easyfix} from './Actions'; -import { Card, CardHeader, CardBody, UncontrolledCollapse } from 'reactstrap'; - -class FedoraManualTestingItemsListSub2 extends Component { - render() { - return(this.props.data.map(action => (
  • ))) - } -} - -class FedoraManualTestingItemsListSub1 extends Component { - render() { - var subsections = Object.keys(this.props.data); - var title = this.props.title; -// if (subsections.length > 1){ - subsections = Object.keys(this.props.data).map(k => ( -
  • {k} - -
  • - ) - ) -/* } - else{ - title = title + ' - ' + subsections[0]; - subsections = Object.keys(this.props.data).map(k => ()); - } -*/ - var l1 =
    ; - switch (this.props.title) { - case "Installation": - l1 = (
    The Installation testcases generally deal with a part of the installation procedure.
    - You will certainly need an installation ISO, and either a Virtual or Bare-metal machine to run the test.
    - Note: some (not that many, though) of these testcases require Bare-metal machine. Be sure to read the Description of the testcase carefully. -
    ); - break; - case "Desktop": - l1 = (
    The Desktop testcases cover basic functionality of the desktop environment.
    - You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live image instead. -
    ); - break; - case "Base": - l1 = (
    The Base testcases cover the system's basic functionality just after a clean installation.
    - Most times, you will be asked to perform a clean Fedora installation. You can use either Virtual or Bare-metal machine.
    - Pro tip: using a snapshot of cleanly installed Virtual machine is just fine. No need to reinstall for every testcase. -
    ); - break; - case "Server": - l1 = (
    The Server testcases usually require multiple machines to test the server-client behaviour, and might feel a bit advanced. -
    ); - break; - case "Cloud": - l1 = (
    Even thought the Cloud testcases are best done in the specific environments like EC2 or Openstack, you can also perform - them locally using Testcloud.
    - Have a look at the Cloud provider setup guides for more details. -
    ); - break; - default: - break; - } - - var toggler="fmt_ai_toggle_"+title; - toggler = toggler.replace(/[\W_]+/g,"_"); - - return( - - - {l1} - Show me! - - - -
      {subsections}
    -
    -
    -
    ); - } -} - -class FedoraManualTestingItemsList extends Component { - render() { - let sections = Object.keys(this.props.data).map(k => ()); - return(
    {sections}
    ) - } -} - - -class EasyfixItemsListSub2 extends Component { - render() { - return(this.props.data.map(action => (
  • ))) - } -} - - -class EasyfixItemsListSub1 extends Component { - render() { - var subsections = Object.keys(this.props.data); - var title = this.props.title; - var btn_expand_class = 'primary'; - var btn_expand_text = "Show me"; - if (subsections.length > 1){ - subsections = Object.keys(this.props.data).map(k => { - - var subtoggler = "easyfix_il_subtoggler_"+title+"_"+k; - subtoggler = subtoggler.replace(/[\W_]+/g,"_"); - - return( - - - {k} - {this.props.data[k][0].extra_data.description} - Show me! - - - -
      - -
    -
    -
    -
    ); - } - ); - title = {title} - Is a group containing several projects. Expand to see more.; - btn_expand_class = 'warning'; - btn_expand_text = 'Expand'; - } - else{ - console.log(this.props.data); - console.log(subsections); - console.log(title); - if (title !== subsections[0]){ - title = {title + '/' + subsections[0]} - {this.props.data[subsections[0]][0].extra_data.description}; - } - else { - title = {title} - {this.props.data[subsections[0]][0].extra_data.description}; - } - subsections = Object.keys(this.props.data).map(k => ( -
    -
      - -
    -
    - ) - ); - } - - var toggler="easyfix_il_toggle_"+this.props.title; - toggler = toggler.replace(/[\W_]+/g,"_"); - - return( - - - {title} - {btn_expand_text}! - - - - {subsections} - - - ); - } -} - - -class EasyfixItemsList extends Component { - render() { - let sections = Object.keys(this.props.data).map(k => ()); - return(
    {sections}
    ) - } -} - -class FedoraEasyKarmaItemsList extends Component { - render() { - if(this.props.data === undefined) return (null) - else return ( -
    -
    What is Karma
    - Before a new version of a package is pushed to the Fedora's Updates repository, it needs to be tested and proved functional.{' '} - Tell me more about the process! - - The updates are kept in Bodhi, 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. - -
    Sure, let me do it!
    -
      -
    1. - Fedora Accounts System (FAS) account is required.{' '} - Don't have one yet? - -
        -
      • Visit FAS Sign-up page and create it.
      • -
      • Note the username and password, you will need it later on.
      • -
      -
      -
    2. -
    3. Make sure your system is up-to-date: sudo dnf update --refresh
    4. -
    5. Install fedora-easy-karma tool: sudo dnf install fedora-easy-karma
    6. -
    7. Choose an update to test{' '} - Not sure how? - - Have a look at the available packages in updates-testing repo, by running dnf --enablerepo=updates-testing list upgrades{' '} - And choose a package you know. - -
    8. -
    9. - Install the package sudo dnf --enablerepo=updates-testing update PACKAGE_NAME, and test whether it works, as you would expect.
      - Note: the package you have chosen might have some dependencies. Be sure to - or at least try to - test those too!{' '} - Need some tips? - - Sometimes, the update associated with the package you just installed fixes some specific bugs, or has testcases associated with it.
      - Run fedora-easy-karma PACKAGE_NAME, and look for Bugs, Test Cases, and/or Notes sections in the detailed output. -
      -
    10. -
    11. - Run fedora-easy-karma --fas-username=FAS_USERNAME and report what you found out.{' '} - New to fedora-easy-karma? - - It identifies the packages installed from the updates-testing repository, and matches them to the updates in Bodhi.
      - Then, you are presented with the relevant updates one-by-one, to submit Karma and a comment. - Not sure what Karma means? - -
        -
      1. - Enter 1 to mark positive karma (the update works just fine, as far as you can tell), or -1{' '} - to mark the package as broken.
        - Not sure you can judge the package's state? Either just press Enter to skip it, or insert i (instead of 1 or -1) to also ignore the package in the future. -
      2. -
      3. - Add a comment - this could be something as simple as Works for me, but make sure to provide reasonable amount of detail, when submitting negative karma (ideally, you should also create a bugreport, and refence it in the comment). -
      4. -
      -
      -
      -
    12. -
    13. Restore the stable-packages on your system by running sudo dnf distro-sync
    14. -
    - -
    - ) - } -} - - - - -export { - FedoraManualTestingItemsList, - EasyfixItemsList, - FedoraEasyKarmaItemsList -} diff --git a/src/Actions.js b/src/Actions.js deleted file mode 100644 index 14c9a5c..0000000 --- a/src/Actions.js +++ /dev/null @@ -1,200 +0,0 @@ -import React, { Component } from 'react'; -import { Modal, ModalHeader, ModalBody, ModalFooter, UncontrolledCollapse } from 'reactstrap'; - - -class Easyfix extends Component { - render() { - const url = this.props.data.extra_data.ticket_url; - const name = this.props.data.name; - - return ({name}); - } -} - -class FedoraManualTesting extends Component { - render() { - - const extra_data = this.props.data.extra_data - - const tc_url = extra_data.testcase_url; - const name = this.props.data.name; - - const matrix_url = extra_data.matrix_url; - var environment_examples = undefined; - switch (extra_data.testtype){ - case "Installation": - environment_examples = x86_64 or ARM; - break; - case "Base": - environment_examples = Workstation, Server, Xfce or Minimal; - break; - case "Desktop": - environment_examples = Workstation or KDE; - break; - case "Server": - environment_examples = x86_64 or aarch64; - break; - default: - break; - } - - const testtype = extra_data.testtype; - const tc_rawname = extra_data.name; - - return ( - -
      -
    1. - Identify the testcase and `environment` in our Tescase matrix  - Not sure what that means? - -
        -
      • - 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 Result column. -
      • -
      • - Find the row with the {tc_rawname} value, and note which of the environments still has no results filled in. -
      • -
      -
      -
    2. - -
    3. - Read the Testcase briefly, just to have a general idea of what you will be doing.  - Not making much sense? - - The testcases are generally split into four sections: -
        -
      • Description should give you a general idea of what is being tested
      • -
      • Setup describes the steps to take before you begin working on the testcase
      • -
      • How to test contains the individual steps to take in order to perform the testcase
      • -
      • Expected results describe what you should check while testing in order to decide whether it Passed of Failed
      • -
      -
      -
    4. - -
    5. - Based on the enviromnent, select and download and appropriate ISO here.  - Not sure how? - -
        -
      • Most of the time Workstation Live, or Server DVD are fine, but sometimes there are specific products (e.g. Xfce) to be tested
      • -
      • - Make sure to read about identifying the environment above. - Show me! -
      • -
      -
      -
    6. - - -
    7. - Study the Testcase thoroughly, to be sure you know what to do.  - Feeling a bit lost? - -
        -
      • - The testcase structure is not making sense? - Click here -
      • -
      • - Maybe you are stuck, or just do not understand something? Feel free to ask on our IRC channel #fedora-qa at freenode.net - Don't have an IRC client? - - If you are not that familiar with IRC, you can use the web-interface - just enter a Nickname of your choice, #fedora-qa (including the hash sign) in the Channels field, and click Connect. - -
      • -
      -
      -
    8. - -
    9. - Get your hands dirty, and test the hell out of it! -
    10. -
    11. - Everything went well  - - Great! - Either use relval report-results on command line (make sure to install the relval package first), - or modify the matrix directly by clicking on the Edit link next to the Matrice's header, - and put {{result|pass|YOUR_NAME_HERE|}} in the appropriate spot. - - - I found a bug! - - Awesome! Ideally read up on https://fedoraproject.org/wiki/How_to_file_a_bug_report
      - If you don't feel like reading a wall of text, at least pot together a small document containing: -
        -
      • Brief description of what went wrong (e.g. "QA:Testcase_dualboot_with_windows - Bootloader does not show the Windows option")
      • -
      • The name of the ISO image you used (e.g. "Fedora-Server-netinst-i386-Rawhide-20181227.n.0.iso")
      • -
      • 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.
      • -
      • 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)
      • -
      • - 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 - Don'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. - -
      • -
      - Once you get the Bug reported, make sure to also submit the result into the testing matrix. - Either use relval report-results on command line (make sure to install the relval package first), - or modify the matrix directly by clicking on the Edit link next to the Matrice's header, - and put {{result|fail|YOUR_NAME_HERE|BUG_NUMBER|}} in the appropriate spot. -
      -
    12. - -
    -
    - ) - } -} - - -class ModalInfo extends Component { - constructor(props) { - super(props); - this.state = { - modal: false - }; - - this.toggle = this.toggle.bind(this); - } - - toggle(e) { - this.setState({ - modal: !this.state.modal - }); - e.preventDefault(); - } - - render() { - const project = this.props.buttonLabel.split(":")[0] - const ticket = this.props.buttonLabel.split(":")[1] //strip whitespace? - - return ( -
    - this.toggle(e)}>{this.props.buttonLabel} - - - {project} - - -
    {ticket}
    - {this.props.children} -
    - - -
    -
    - ); - } - -} - -export { - Easyfix, - FedoraManualTesting -} diff --git a/src/App.css b/src/App.css deleted file mode 100644 index e69de29..0000000 --- a/src/App.css +++ /dev/null diff --git a/src/App.js b/src/App.js index f524207..b782aa0 100644 --- a/src/App.js +++ b/src/App.js @@ -3,10 +3,9 @@ import React, { Component } from 'react'; import { Route, Switch } from 'react-router'; import { BrowserRouter } from 'react-router-dom' -import Wizard from './Wizard'; -import LandingPage from './LandingPage'; +import Wizard from './wizard/Wizard'; +import LandingPage from './landingpage/LandingPage'; import NotFound from './NotFound'; -import './App.css'; class App extends Component { diff --git a/src/App.test.js b/src/App.test.js deleted file mode 100644 index a754b20..0000000 --- a/src/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); -}); diff --git a/src/Blockers.js b/src/Blockers.js deleted file mode 100644 index 0e7fc56..0000000 --- a/src/Blockers.js +++ /dev/null @@ -1,88 +0,0 @@ -import React, { Component } from 'react'; -import { Row } from 'reactstrap'; - -class Blockers extends Component { - constructor(props) { - super(props); - this.state = { blockerbugs: {}, release: 0 }; - } - - componentDidMount() { - fetch(this.props.apiurl + 'blockerbugs') - .then(data => { - return data.json(); - }) - .then(data => { - console.log(data); - this.setState({ - blockerbugs: data.blockerbugs, - release: data.release - }); - }); - } - render() { - if (this.state.blockerbugs) - return ( -
    - -
    Fedora {this.state.release} blockers and FEs{' '} - - - -
    - -
    - - - - - - - - - - - - - - - - - - - - -
    Beta
    Proposed Blockers{this.state.blockerbugs.beta_blockers_proposed}
    Accepted Blockers{this.state.blockerbugs.beta_blockers}
    Proposed FEs{this.state.blockerbugs.beta_fe_proposed}
    Accepted FEs{this.state.blockerbugs.beta_fe}
    -
    - -
    - - - - - - - - - - - - - - - - - - - - -
    Final
    Proposed Blockers{this.state.blockerbugs.final_blockers_proposed}
    Accepted Blockers{this.state.blockerbugs.final_blockers}
    Proposed FEs{this.state.blockerbugs.final_fe_proposed}
    Accepted FEs{this.state.blockerbugs.final_fe}
    -
    -
    -
    - ); - } -} - - -export default Blockers; diff --git a/src/Events.js b/src/Events.js deleted file mode 100644 index 1d13622..0000000 --- a/src/Events.js +++ /dev/null @@ -1,62 +0,0 @@ -import React, { Component } from 'react'; -import dateFormat from 'dateformat'; - -class Events extends Component { - constructor(props) { - super(props); - this.state = { meetings: [] }; - } - - componentDidMount() { - fetch(this.props.apiurl + 'meetings') - .then(data => { - return data.json(); - }) - .then(data => { - console.log(data); - this.setState({ meetings: data.meetings }); - }); - } - - render() { - const meetings = this.state.meetings.map(meeting => { - const old = new Date(meeting.start); - meeting.start = dateFormat(new Date(old.getTime() - old.getTimezoneOffset()*60000), "d mmm yyyy - HH:MM") - if (meeting.fullday){ - meeting.start = meeting.start.slice(0,-5) + "All day" - } - return () - }); - return ( -
    -
    - Meetings and testdays in the next 7 days{' '} - - - -
    -
      - {meetings} -
    -
    - ); - } -} - -class Event extends Component { - render() { - return ( -
  • - {this.props.start} -
    - {this.props.summary} -
    -
  • - ); - } -} - - - - -export default Events; diff --git a/src/Footer.js b/src/Footer.js deleted file mode 100644 index c635a80..0000000 --- a/src/Footer.js +++ /dev/null @@ -1,14 +0,0 @@ -import React, { Component } from 'react'; - - -class Footer extends Component { - render() { - return ( -
    - {this.props.children} -
    - ); - } -} - -export default Footer; diff --git a/src/LandingPage.js b/src/LandingPage.js deleted file mode 100644 index 17f9631..0000000 --- a/src/LandingPage.js +++ /dev/null @@ -1,53 +0,0 @@ -import React, { Component } from 'react'; -import { Container, Row } from 'reactstrap'; -import { Link } from 'react-router-dom' -import Layout from './Layout'; -import Timeline from "./Timeline"; -import Events from "./Events"; -import Blockers from "./Blockers"; -import {oraculumApiUrl} from "./config"; - - -class LandingPage extends Component { - render() { - return ( - -
    - - -
    - -
    -
    -
    -
    - - -
    - -
    -
    - -
    -
    -{/* - -
    - -
    -
    -*/} - -
    - - Do you have some spare time? Feeling like helping others? Wanna improve Fedora? Click here! - -
    -
    -
    -
    - ) - } -} - -export default LandingPage; diff --git a/src/Layout.js b/src/Layout.js deleted file mode 100644 index 3463a81..0000000 --- a/src/Layout.js +++ /dev/null @@ -1,16 +0,0 @@ -import React, { Component } from 'react'; -import Masthead from './Masthead'; - - -class Layout extends Component { - render() { - return ( -
    - - {this.props.children} -
    - ); - } -} - -export default Layout; diff --git a/src/Masthead.js b/src/Masthead.js deleted file mode 100644 index f6b9960..0000000 --- a/src/Masthead.js +++ /dev/null @@ -1,25 +0,0 @@ -import React, { Component } from 'react'; -import { Link } from 'react-router-dom' -import { Container, NavbarBrand, Nav, NavItem, Navbar } from 'reactstrap'; - -import logo from './logo.png'; - - -class Masthead extends Component { - render() { - return ( - - - - - - - ); - } -} - -export default Masthead; diff --git a/src/Minutes.js b/src/Minutes.js deleted file mode 100644 index 679ead1..0000000 --- a/src/Minutes.js +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react'; - -class Events extends Component { - constructor(props) { - super(props); - this.state = { link: "", date: "" }; - } - - componentDidMount() { - fetch(this.props.apiurl + 'last_qa_meeting') - .then(data => { - return data.json(); - }) - .then(data => { - console.log(data); - this.setState({ link: data.link, date: data.date }); - }); - } - render() { - - return ( -
    -
    - Latest QA Meeting Minutes From {this.state.date} -
    - Here! -
    - ); - } -} - - -export default Events; diff --git a/src/NotFound.js b/src/NotFound.js index 79a81e8..4343834 100644 --- a/src/NotFound.js +++ b/src/NotFound.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import Layout from './Layout'; +import Layout from './layout/Layout'; import { Container } from 'reactstrap'; @@ -14,7 +14,6 @@ class Wizard extends Component {

    - ) } } diff --git a/src/Timeline.js b/src/Timeline.js deleted file mode 100644 index 73d3f5d..0000000 --- a/src/Timeline.js +++ /dev/null @@ -1,94 +0,0 @@ -import React, { Component } from 'react'; - - -class Timeline extends Component { - constructor(props) { - super(props); - this.state = { schedule: [] }; - } - - componentDidMount() { - fetch(this.props.apiurl + 'schedule') - .then(data => { - return data.json(); - }) - .then(data => { - console.log(data); - this.setState({ schedule: data.schedule }); - }); - } - - 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." - if (summary === "rawhide") - return "Next Fedora release hasn't been branched yet from rolling release branch." - if (summary.includes("branch")) - return "Next version of Fedora that was 'branched' from the rolling Rawhide tree and in the future will become the next stable Fedora release." - if (summary.includes("release")) - return "Release candidate was accepted (violating no milestone criteria) and was released." - } - - render() { - const line = this.state.schedule.map(milestone => { - return ( - - - - ) - }) - - const dates = this.state.schedule.map(milestone => { - return ( - - {milestone.date} - - ) - }); - - const schedule = this.state.schedule.map(milestone => { - return ( - - {milestone.summary}{' '} - - ) - }); - return ( -
    -
    Current development schedule{' '} - - - -
    -
    - - - {line} - {dates} - {schedule} - -
    -
    -
    - ); - } -} - -class Line extends Component { - render() { - const lineStyle = { - stroke: this.props.color, - strokeWidth: "3" - } - return ( - - - - - ) - } -} - - -export default Timeline; diff --git a/src/Wizard.js b/src/Wizard.js deleted file mode 100644 index 9437364..0000000 --- a/src/Wizard.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, { Component } from 'react'; -import WizardForm from './WizardForm'; -import Layout from './Layout'; -import { oraculumApiUrl_v1 } from './config'; -import { FedoraManualTestingItemsList, EasyfixItemsList, FedoraEasyKarmaItemsList } from './ActionItems'; -import _ from 'lodash'; -import { Container, Row } from 'reactstrap'; - -class Wizard extends Component { - constructor(props) { - super(props) - this.state = { - actions: [], - } - } - - set_actions(actions){ - this.setState({actions}) - } - - render_actions() { - var outdata = [] - const grouped = _(this.state.actions) - .groupBy(action=>action.provider) - .value() - - outdata.push( - a.extra_data.testtype) - .mapValues(v => _(v).groupBy(a=>a.extra_data.section).value()) - .value() - } key='fmtl' /> - ) - outdata.push( - a.extra_data.repo_org) - .mapValues(v => _(v).groupBy(a=>a.extra_data.repo_name).value()) - .value() - } key='easyfix' /> - ) - outdata.push( - - ) - - return ( -
    - {outdata} -
    - ) - } - - render() { - return ( - -
    - - - -
    - - - {this.render_actions()} - - -
    - - ) - } -} - -export default Wizard; diff --git a/src/WizardForm.js b/src/WizardForm.js deleted file mode 100644 index 99188db..0000000 --- a/src/WizardForm.js +++ /dev/null @@ -1,156 +0,0 @@ -import React, { Component } from 'react'; -import { Row, Button } from 'reactstrap'; - - -const durationString = { - "3": "Few hours", - "72": "Several days", -} - - - -class WizardForm extends Component { - constructor(props) { - super(props) - this.state = { - //doable actions - actions: [], - - //v2 rewrite - providers: [], - selected_provider: "", - selected_provider_tags: [], - tags_enabled: false - } - - this.known_primary_tags = ["Programming", "Testing"] - } - - componentDidMount() { - fetch(this.props.apiurl + "actions/providers") - .then(resp => resp.json()) - .then(data => { - this.setState({ - providers: data.providers - }) - }) - } - - provider_selected(provider) { - console.log(provider) - fetch(this.props.apiurl + "actions/tags?provider=" + provider.name) - .then(resp => resp.json()) - .then(data => { - this.props.set_actions([]); - this.setState({ - selected_provider: provider, - selected_provider_tags: data.tags, - tags_enabled: true, - }, () => { - if (!provider.tags) - this._tags_selected(data.tags) - }) - }) - } - - _tags_selected(tags) { - const encoded_tags = tags.map(t => encodeURIComponent(t)) - fetch(this.props.apiurl + 'actions?provider=' + this.state.selected_provider.name + "&tags=" + encoded_tags.join(',')) - .then(resp => resp.json()) - .then(data => { - /* - this.setState({ - actions: data.actions - }) - */ - this.props.set_actions(data.actions) - }) - } - tags_selected(e) { - const tags = [].slice.call(e.target.selectedOptions).map(o => o.value); - this._tags_selected(tags) - } - - tag_handler(t){ - this._tags_selected([t]) - } - - get_tag_selector(){ - if (this.state.selected_provider === "" || !this.state.selected_provider.tags) - return (null) - else - return ( - -
    -
    Make your choice!
    - -
    -
    - ) - } - - render() { - const providers = [3, 72].map(duration => { - const duration_providers = this.state.providers.filter(p => p.duration === duration).map(p => { - return ( - -
    - {p.scope} - {p.name_human}: {p.description} -
    -
    - -
    -
    - ) - }) - - return ( -
    -
    {durationString[duration]}
    - {duration_providers} -
    - ) - }) - - return ( -
    - -
    - {providers} -
    -
    - {this.get_tag_selector()} -
    - ) - } -} - -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?'success':'primary'; - } - - render(){ - var x = this.props.data.map(t => ( - - )); - return (
    {x}
    ) - } -} - - -export default WizardForm; diff --git a/src/index.css b/src/index.css index 1ebf737..35caf1b 100644 --- a/src/index.css +++ b/src/index.css @@ -1,4 +1,17 @@ +html { + height: 100%; + box-sizing: border-box; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + body { + position: relative; + min-height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", @@ -6,6 +19,8 @@ body { sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + + padding-bottom: 10rem; } code { @@ -37,13 +52,11 @@ code { .footer { position: absolute; - display: flex; - align-items: center; - justify-content: center; + right: 0; bottom: 0; - width: 100%; - height: 100px; - vertical-align: middle; + left: 0; + padding: 1rem; + text-align: center; color: #bbb; } diff --git a/src/landingpage/Blockers.js b/src/landingpage/Blockers.js new file mode 100644 index 0000000..0e7fc56 --- /dev/null +++ b/src/landingpage/Blockers.js @@ -0,0 +1,88 @@ +import React, { Component } from 'react'; +import { Row } from 'reactstrap'; + +class Blockers extends Component { + constructor(props) { + super(props); + this.state = { blockerbugs: {}, release: 0 }; + } + + componentDidMount() { + fetch(this.props.apiurl + 'blockerbugs') + .then(data => { + return data.json(); + }) + .then(data => { + console.log(data); + this.setState({ + blockerbugs: data.blockerbugs, + release: data.release + }); + }); + } + render() { + if (this.state.blockerbugs) + return ( +
    + +
    Fedora {this.state.release} blockers and FEs{' '} + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + +
    Beta
    Proposed Blockers{this.state.blockerbugs.beta_blockers_proposed}
    Accepted Blockers{this.state.blockerbugs.beta_blockers}
    Proposed FEs{this.state.blockerbugs.beta_fe_proposed}
    Accepted FEs{this.state.blockerbugs.beta_fe}
    +
    + +
    + + + + + + + + + + + + + + + + + + + + +
    Final
    Proposed Blockers{this.state.blockerbugs.final_blockers_proposed}
    Accepted Blockers{this.state.blockerbugs.final_blockers}
    Proposed FEs{this.state.blockerbugs.final_fe_proposed}
    Accepted FEs{this.state.blockerbugs.final_fe}
    +
    +
    +
    + ); + } +} + + +export default Blockers; diff --git a/src/landingpage/Events.js b/src/landingpage/Events.js new file mode 100644 index 0000000..1d13622 --- /dev/null +++ b/src/landingpage/Events.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react'; +import dateFormat from 'dateformat'; + +class Events extends Component { + constructor(props) { + super(props); + this.state = { meetings: [] }; + } + + componentDidMount() { + fetch(this.props.apiurl + 'meetings') + .then(data => { + return data.json(); + }) + .then(data => { + console.log(data); + this.setState({ meetings: data.meetings }); + }); + } + + render() { + const meetings = this.state.meetings.map(meeting => { + const old = new Date(meeting.start); + meeting.start = dateFormat(new Date(old.getTime() - old.getTimezoneOffset()*60000), "d mmm yyyy - HH:MM") + if (meeting.fullday){ + meeting.start = meeting.start.slice(0,-5) + "All day" + } + return () + }); + return ( +
    +
    + Meetings and testdays in the next 7 days{' '} + + + +
    +
      + {meetings} +
    +
    + ); + } +} + +class Event extends Component { + render() { + return ( +
  • + {this.props.start} +
    + {this.props.summary} +
    +
  • + ); + } +} + + + + +export default Events; diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js new file mode 100644 index 0000000..bd3474a --- /dev/null +++ b/src/landingpage/LandingPage.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react'; +import { Container, Row } from 'reactstrap'; +import { Link } from 'react-router-dom' +import Layout from '../layout/Layout'; +import Timeline from "./Timeline"; +import Events from "./Events"; +import Blockers from "./Blockers"; +import {oraculumApiUrl} from "../config"; + + +class LandingPage extends Component { + render() { + return ( + +
    + + +
    + +
    +
    +
    +
    + + +
    + +
    +
    + +
    +
    +{/* + +
    + +
    +
    +*/} + +
    + + Do you have some spare time? Feeling like helping others? Wanna improve Fedora? Click here! + +
    +
    +
    +
    + ) + } +} + +export default LandingPage; diff --git a/src/landingpage/Minutes.js b/src/landingpage/Minutes.js new file mode 100644 index 0000000..679ead1 --- /dev/null +++ b/src/landingpage/Minutes.js @@ -0,0 +1,33 @@ +import React, { Component } from 'react'; + +class Events extends Component { + constructor(props) { + super(props); + this.state = { link: "", date: "" }; + } + + componentDidMount() { + fetch(this.props.apiurl + 'last_qa_meeting') + .then(data => { + return data.json(); + }) + .then(data => { + console.log(data); + this.setState({ link: data.link, date: data.date }); + }); + } + render() { + + return ( +
    +
    + Latest QA Meeting Minutes From {this.state.date} +
    + Here! +
    + ); + } +} + + +export default Events; diff --git a/src/landingpage/Timeline.js b/src/landingpage/Timeline.js new file mode 100644 index 0000000..73d3f5d --- /dev/null +++ b/src/landingpage/Timeline.js @@ -0,0 +1,94 @@ +import React, { Component } from 'react'; + + +class Timeline extends Component { + constructor(props) { + super(props); + this.state = { schedule: [] }; + } + + componentDidMount() { + fetch(this.props.apiurl + 'schedule') + .then(data => { + return data.json(); + }) + .then(data => { + console.log(data); + this.setState({ schedule: data.schedule }); + }); + } + + 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." + if (summary === "rawhide") + return "Next Fedora release hasn't been branched yet from rolling release branch." + if (summary.includes("branch")) + return "Next version of Fedora that was 'branched' from the rolling Rawhide tree and in the future will become the next stable Fedora release." + if (summary.includes("release")) + return "Release candidate was accepted (violating no milestone criteria) and was released." + } + + render() { + const line = this.state.schedule.map(milestone => { + return ( + + + + ) + }) + + const dates = this.state.schedule.map(milestone => { + return ( + + {milestone.date} + + ) + }); + + const schedule = this.state.schedule.map(milestone => { + return ( + + {milestone.summary}{' '} + + ) + }); + return ( +
    +
    Current development schedule{' '} + + + +
    +
    + + + {line} + {dates} + {schedule} + +
    +
    +
    + ); + } +} + +class Line extends Component { + render() { + const lineStyle = { + stroke: this.props.color, + strokeWidth: "3" + } + return ( + + + + + ) + } +} + + +export default Timeline; diff --git a/src/layout/Footer.js b/src/layout/Footer.js new file mode 100644 index 0000000..2124e21 --- /dev/null +++ b/src/layout/Footer.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; + + +class Footer extends Component { + render() { + return ( +
    +
    +
    Fedora QA Dashboard 0.1.0
    +
    +
    +
    Source on Pagure
    +
    +
    + ); + } +} + +export default Footer; diff --git a/src/layout/Layout.js b/src/layout/Layout.js new file mode 100644 index 0000000..2cde16e --- /dev/null +++ b/src/layout/Layout.js @@ -0,0 +1,18 @@ +import React, { Component } from 'react'; +import Masthead from './Masthead'; +import Footer from './Footer'; + + +class Layout extends Component { + render() { + return ( +
    + + {this.props.children} +
    +
    + ); + } +} + +export default Layout; diff --git a/src/layout/Masthead.js b/src/layout/Masthead.js new file mode 100644 index 0000000..114bc16 --- /dev/null +++ b/src/layout/Masthead.js @@ -0,0 +1,20 @@ +import React, { Component } from 'react'; +import { Link } from 'react-router-dom' +import { Container, NavbarBrand, Navbar } from 'reactstrap'; + +import logo from './logo.png'; + + +class Masthead extends Component { + render() { + return ( + + + + + + ); + } +} + +export default Masthead; diff --git a/src/layout/logo.png b/src/layout/logo.png new file mode 100755 index 0000000..ec8aa53 Binary files /dev/null and b/src/layout/logo.png differ diff --git a/src/logo.png b/src/logo.png deleted file mode 100755 index ec8aa53..0000000 Binary files a/src/logo.png and /dev/null differ diff --git a/src/wizard/Actions.js b/src/wizard/Actions.js new file mode 100644 index 0000000..b312e19 --- /dev/null +++ b/src/wizard/Actions.js @@ -0,0 +1,44 @@ +import React, { Component } from 'react' + +import Easyfix from "./Easyfix"; +import FedoraManualTesting from "./FedoraManualTesting"; +import FedoraEasyKarma from "./FedoraEasyKarma" + +import _ from 'lodash'; + +export class Actions extends Component { + render() { + var outdata = [] + const grouped = _(this.props.data) + .groupBy(action => action.provider) + .value() + + outdata.push( + a.extra_data.testtype) + .mapValues(v => _(v).groupBy(a => a.extra_data.section).value()) + .value() + } key='fmtl' /> + ) + outdata.push( + a.extra_data.repo_org) + .mapValues(v => _(v).groupBy(a => a.extra_data.repo_name).value()) + .value() + } key='easyfix' /> + ) + outdata.push( + + ) + + return ( +
    + {outdata} +
    + ) + } +} + +export default Actions diff --git a/src/wizard/Easyfix.js b/src/wizard/Easyfix.js new file mode 100644 index 0000000..dacc270 --- /dev/null +++ b/src/wizard/Easyfix.js @@ -0,0 +1,98 @@ +import React, { Component } from 'react'; +import { Card, CardHeader, CardBody, UncontrolledCollapse } from 'reactstrap'; + + +export default class Easyfix extends Component { + render() { + let sections = Object.keys(this.props.data).map(k => ()); + return(
    {sections}
    ) + } +} + + +class EasyfixItemsListSub2 extends Component { + render() { + const items = this.props.data.map(action => ( +
  • + + {action.name} + +
  • + )) + + return ( +
      + {items} +
    + ) + } +} + + +class EasyfixItemsListSub1 extends Component { + render() { + var subsections = Object.keys(this.props.data); + var title = this.props.title; + var btn_expand_class = 'primary'; + var btn_expand_text = "Show me"; + if (subsections.length > 1){ + subsections = Object.keys(this.props.data).map(k => { + + var subtoggler = "easyfix_il_subtoggler_"+title+"_"+k; + subtoggler = subtoggler.replace(/[\W_]+/g,"_"); + + return( + + + {k} - {this.props.data[k][0].extra_data.description} + Show me! + + + + + + + ); + } + ); + title = {title} - Is a group containing several projects. Expand to see more.; + btn_expand_class = 'warning'; + btn_expand_text = 'Expand'; + } + else{ + if (title !== subsections[0]){ + title = {title + '/' + subsections[0]} - {this.props.data[subsections[0]][0].extra_data.description}; + } + else { + title = {title} - {this.props.data[subsections[0]][0].extra_data.description}; + } + subsections = Object.keys(this.props.data).map(k => ( +
    +
      + +
    +
    + ) + ); + } + + var toggler="easyfix_il_toggle_"+this.props.title; + toggler = toggler.replace(/[\W_]+/g,"_"); + + return( + + + {title} + {btn_expand_text}! + + + + {subsections} + + + ); + } +} + + + diff --git a/src/wizard/FedoraEasyKarma.js b/src/wizard/FedoraEasyKarma.js new file mode 100644 index 0000000..5efdda7 --- /dev/null +++ b/src/wizard/FedoraEasyKarma.js @@ -0,0 +1,75 @@ +import React, { Component } from 'react'; +import { UncontrolledCollapse } from 'reactstrap'; + + +export default class FedoraEasyKarmaItemsList extends Component { + render() { + if(this.props.data === undefined) return (null) + else return ( +
    +
    What is Karma
    + Before a new version of a package is pushed to the Fedora's Updates repository, it needs to be tested and proved functional.{' '} + Tell me more about the process! + + The updates are kept in Bodhi, 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. + +
    Sure, let me do it!
    +
      +
    1. + Fedora Accounts System (FAS) account is required.{' '} + Don't have one yet? + +
        +
      • Visit FAS Sign-up page and create it.
      • +
      • Note the username and password, you will need it later on.
      • +
      +
      +
    2. +
    3. Make sure your system is up-to-date: sudo dnf update --refresh
    4. +
    5. Install fedora-easy-karma tool: sudo dnf install fedora-easy-karma
    6. +
    7. Choose an update to test{' '} + Not sure how? + + Have a look at the available packages in updates-testing repo, by running dnf --enablerepo=updates-testing list upgrades{' '} + And choose a package you know. + +
    8. +
    9. + Install the package sudo dnf --enablerepo=updates-testing update PACKAGE_NAME, and test whether it works, as you would expect.
      + Note: the package you have chosen might have some dependencies. Be sure to - or at least try to - test those too!{' '} + Need some tips? + + Sometimes, the update associated with the package you just installed fixes some specific bugs, or has testcases associated with it.
      + Run fedora-easy-karma PACKAGE_NAME, and look for Bugs, Test Cases, and/or Notes sections in the detailed output. +
      +
    10. +
    11. + Run fedora-easy-karma --fas-username=FAS_USERNAME and report what you found out.{' '} + New to fedora-easy-karma? + + It identifies the packages installed from the updates-testing repository, and matches them to the updates in Bodhi.
      + Then, you are presented with the relevant updates one-by-one, to submit Karma and a comment. + Not sure what Karma means? + +
        +
      1. + Enter 1 to mark positive karma (the update works just fine, as far as you can tell), or -1{' '} + to mark the package as broken.
        + Not sure you can judge the package's state? Either just press Enter to skip it, or insert i (instead of 1 or -1) to also ignore the package in the future. +
      2. +
      3. + Add a comment - this could be something as simple as Works for me, but make sure to provide reasonable amount of detail, when submitting negative karma (ideally, you should also create a bugreport, and refence it in the comment). +
      4. +
      +
      +
      +
    12. +
    13. Restore the stable-packages on your system by running sudo dnf distro-sync
    14. +
    + +
    + ) + } +} \ No newline at end of file diff --git a/src/wizard/FedoraManualTesting.js b/src/wizard/FedoraManualTesting.js new file mode 100644 index 0000000..c95f343 --- /dev/null +++ b/src/wizard/FedoraManualTesting.js @@ -0,0 +1,271 @@ +import React, { Component } from 'react'; +import { Card, CardHeader, CardBody, UncontrolledCollapse } from 'reactstrap'; +import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; + +export default class FedoraManualTesting extends Component { + render() { + let sections = Object.keys(this.props.data).map(k => ()); + return(
    {sections}
    ) + } +} + + +class FedoraManualTestingItemsListSub2 extends Component { + render() { + return(this.props.data.map(action => (
  • ))) + } +} + +class FedoraManualTestingItemsListSub1 extends Component { + render() { + var subsections = Object.keys(this.props.data); + var title = this.props.title; +// if (subsections.length > 1){ + subsections = Object.keys(this.props.data).map(k => ( +
  • {k} +
      + +
    +
  • + ) + ) +/* } + else{ + title = title + ' - ' + subsections[0]; + subsections = Object.keys(this.props.data).map(k => ()); + } +*/ + var l1 =
    ; + switch (this.props.title) { + case "Installation": + l1 = (
    The Installation testcases generally deal with a part of the installation procedure.
    + You will certainly need an installation ISO, and either a Virtual or Bare-metal machine to run the test.
    + Note: some (not that many, though) of these testcases require Bare-metal machine. Be sure to read the Description of the testcase carefully. +
    ); + break; + case "Desktop": + l1 = (
    The Desktop testcases cover basic functionality of the desktop environment.
    + You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live image instead. +
    ); + break; + case "Base": + l1 = (
    The Base testcases cover the system's basic functionality just after a clean installation.
    + Most times, you will be asked to perform a clean Fedora installation. You can use either Virtual or Bare-metal machine.
    + Pro tip: using a snapshot of cleanly installed Virtual machine is just fine. No need to reinstall for every testcase. +
    ); + break; + case "Server": + l1 = (
    The Server testcases usually require multiple machines to test the server-client behaviour, and might feel a bit advanced. +
    ); + break; + case "Cloud": + l1 = (
    Even thought the Cloud testcases are best done in the specific environments like EC2 or Openstack, you can also perform + them locally using Testcloud.
    + Have a look at the Cloud provider setup guides for more details. +
    ); + break; + default: + break; + } + + var toggler="fmt_ai_toggle_"+title; + toggler = toggler.replace(/[\W_]+/g,"_"); + + return( + + + {l1} + Show me! + + + +
      {subsections}
    +
    +
    +
    ); + } +} + + +class FedoraManualTestingItem extends Component { + render() { + + const extra_data = this.props.data.extra_data + + const tc_url = extra_data.testcase_url; + const name = this.props.data.name; + + const matrix_url = extra_data.matrix_url; + var environment_examples = undefined; + switch (extra_data.testtype){ + case "Installation": + environment_examples = x86_64 or ARM; + break; + case "Base": + environment_examples = Workstation, Server, Xfce or Minimal; + break; + case "Desktop": + environment_examples = Workstation or KDE; + break; + case "Server": + environment_examples = x86_64 or aarch64; + break; + default: + break; + } + + const testtype = extra_data.testtype; + const tc_rawname = extra_data.name; + + return ( + +
      +
    1. + Identify the testcase and `environment` in our Tescase matrix  + Not sure what that means? + +
        +
      • + 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 Result column. +
      • +
      • + Find the row with the {tc_rawname} value, and note which of the environments still has no results filled in. +
      • +
      +
      +
    2. + +
    3. + Read the Testcase briefly, just to have a general idea of what you will be doing.  + Not making much sense? + + The testcases are generally split into four sections: +
        +
      • Description should give you a general idea of what is being tested
      • +
      • Setup describes the steps to take before you begin working on the testcase
      • +
      • How to test contains the individual steps to take in order to perform the testcase
      • +
      • Expected results describe what you should check while testing in order to decide whether it Passed of Failed
      • +
      +
      +
    4. + +
    5. + Based on the enviromnent, select and download and appropriate ISO here.  + Not sure how? + +
        +
      • Most of the time Workstation Live, or Server DVD are fine, but sometimes there are specific products (e.g. Xfce) to be tested
      • +
      • + Make sure to read about identifying the environment above. + Show me! +
      • +
      +
      +
    6. + + +
    7. + Study the Testcase thoroughly, to be sure you know what to do.  + Feeling a bit lost? + +
        +
      • + The testcase structure is not making sense? + Click here +
      • +
      • + Maybe you are stuck, or just do not understand something? Feel free to ask on our IRC channel #fedora-qa at freenode.net + Don't have an IRC client? + + If you are not that familiar with IRC, you can use the web-interface + just enter a Nickname of your choice, #fedora-qa (including the hash sign) in the Channels field, and click Connect. + +
      • +
      +
      +
    8. + +
    9. + Get your hands dirty, and test the hell out of it! +
    10. +
    11. + Everything went well  + + Great! + Either use relval report-results on command line (make sure to install the relval package first), + or modify the matrix directly by clicking on the Edit link next to the Matrice's header, + and put {{result|pass|YOUR_NAME_HERE|}} in the appropriate spot. + + + I found a bug! + + Awesome! Ideally read up on https://fedoraproject.org/wiki/How_to_file_a_bug_report
      + If you don't feel like reading a wall of text, at least pot together a small document containing: +
        +
      • Brief description of what went wrong (e.g. "QA:Testcase_dualboot_with_windows - Bootloader does not show the Windows option")
      • +
      • The name of the ISO image you used (e.g. "Fedora-Server-netinst-i386-Rawhide-20181227.n.0.iso")
      • +
      • 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.
      • +
      • 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)
      • +
      • + 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 + Don'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. + +
      • +
      + Once you get the Bug reported, make sure to also submit the result into the testing matrix. + Either use relval report-results on command line (make sure to install the relval package first), + or modify the matrix directly by clicking on the Edit link next to the Matrice's header, + and put {{result|fail|YOUR_NAME_HERE|BUG_NUMBER|}} in the appropriate spot. +
      +
    12. + +
    +
    + ) + } +} + + +class ModalInfo extends Component { + constructor(props) { + super(props); + this.state = { + modal: false + }; + + this.toggle = this.toggle.bind(this); + } + + toggle(e) { + this.setState({ + modal: !this.state.modal + }); + e.preventDefault(); + } + + render() { + const project = this.props.buttonLabel.split(":")[0] + const ticket = this.props.buttonLabel.split(":")[1] //strip whitespace? + + return ( +
    + this.toggle(e)}>{this.props.buttonLabel} + + + {project} + + +
    {ticket}
    + {this.props.children} +
    + + +
    +
    + ); + } + +} diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js new file mode 100644 index 0000000..3cc2ee4 --- /dev/null +++ b/src/wizard/Wizard.js @@ -0,0 +1,40 @@ +import React, { Component } from 'react'; +import WizardForm from './WizardForm'; +import Layout from '../layout/Layout'; +import { oraculumApiUrl_v1 } from '../config'; +import Actions from './Actions'; +import { Container, Row } from 'reactstrap'; + +class Wizard extends Component { + constructor(props) { + super(props) + this.state = { + actions: [], + } + } + + set_actions(actions){ + this.setState({actions}) + } + + render() { + return ( + +
    + + + +
    + + +
    + +
    +
    +
    +
    + ) + } +} + +export default Wizard; diff --git a/src/wizard/WizardForm.js b/src/wizard/WizardForm.js new file mode 100644 index 0000000..99188db --- /dev/null +++ b/src/wizard/WizardForm.js @@ -0,0 +1,156 @@ +import React, { Component } from 'react'; +import { Row, Button } from 'reactstrap'; + + +const durationString = { + "3": "Few hours", + "72": "Several days", +} + + + +class WizardForm extends Component { + constructor(props) { + super(props) + this.state = { + //doable actions + actions: [], + + //v2 rewrite + providers: [], + selected_provider: "", + selected_provider_tags: [], + tags_enabled: false + } + + this.known_primary_tags = ["Programming", "Testing"] + } + + componentDidMount() { + fetch(this.props.apiurl + "actions/providers") + .then(resp => resp.json()) + .then(data => { + this.setState({ + providers: data.providers + }) + }) + } + + provider_selected(provider) { + console.log(provider) + fetch(this.props.apiurl + "actions/tags?provider=" + provider.name) + .then(resp => resp.json()) + .then(data => { + this.props.set_actions([]); + this.setState({ + selected_provider: provider, + selected_provider_tags: data.tags, + tags_enabled: true, + }, () => { + if (!provider.tags) + this._tags_selected(data.tags) + }) + }) + } + + _tags_selected(tags) { + const encoded_tags = tags.map(t => encodeURIComponent(t)) + fetch(this.props.apiurl + 'actions?provider=' + this.state.selected_provider.name + "&tags=" + encoded_tags.join(',')) + .then(resp => resp.json()) + .then(data => { + /* + this.setState({ + actions: data.actions + }) + */ + this.props.set_actions(data.actions) + }) + } + tags_selected(e) { + const tags = [].slice.call(e.target.selectedOptions).map(o => o.value); + this._tags_selected(tags) + } + + tag_handler(t){ + this._tags_selected([t]) + } + + get_tag_selector(){ + if (this.state.selected_provider === "" || !this.state.selected_provider.tags) + return (null) + else + return ( + +
    +
    Make your choice!
    + +
    +
    + ) + } + + render() { + const providers = [3, 72].map(duration => { + const duration_providers = this.state.providers.filter(p => p.duration === duration).map(p => { + return ( + +
    + {p.scope} - {p.name_human}: {p.description} +
    +
    + +
    +
    + ) + }) + + return ( +
    +
    {durationString[duration]}
    + {duration_providers} +
    + ) + }) + + return ( +
    + +
    + {providers} +
    +
    + {this.get_tag_selector()} +
    + ) + } +} + +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?'success':'primary'; + } + + render(){ + var x = this.props.data.map(t => ( + + )); + return (
    {x}
    ) + } +} + + +export default WizardForm;