diff options
Diffstat (limited to 'ui/app/components/wizard')
| -rw-r--r-- | ui/app/components/wizard/add_provider_modal.js | 61 | ||||
| -rw-r--r-- | ui/app/components/wizard/index.js | 19 | ||||
| -rw-r--r-- | ui/app/components/wizard/provider_select_stage.js | 168 | ||||
| -rw-r--r-- | ui/app/components/wizard/register_stage.js | 102 | 
4 files changed, 286 insertions, 64 deletions
| diff --git a/ui/app/components/wizard/add_provider_modal.js b/ui/app/components/wizard/add_provider_modal.js index bc5e023..d54ec08 100644 --- a/ui/app/components/wizard/add_provider_modal.js +++ b/ui/app/components/wizard/add_provider_modal.js @@ -3,12 +3,13 @@  //  import React from 'react' -import { FormGroup, ControlLabel, FormControl, HelpBlock, Button, Modal } from 'react-bootstrap' -import Spinner from '../spinner' -import Validate from '../../lib/validate' -import App from '../../app' +import { FormGroup, ControlLabel, FormControl, HelpBlock, Button, ButtonToolbar, Modal } from 'react-bootstrap' -class AddProviderModal extends React.Component { +import Spinner from 'components/spinner' +import Validate from 'lib/validate' +import Provider from 'models/provider' + +export default class AddProviderModal extends React.Component {    static get defaultProps() {return{      title: 'Add a provider', @@ -18,20 +19,36 @@ class AddProviderModal extends React.Component {    constructor(props) {      super(props)      this.state = { -      validationState: null, +      validationState: null,  // one of 'success', 'error', 'warning'        errorMsg: null, -      domain: "" +      domain: "", +      working: false,         // true if waiting for something      }      this.accept   = this.accept.bind(this)      this.cancel   = this.cancel.bind(this)      this.changed  = this.changed.bind(this)    } -  accept() { +  accept(e=null) { +    if (e) { +      e.preventDefault() // don't reload the page please! +    }      if (this.state.domain) { -      App.providers.add(this.state.domain) +      this.setState({working: true}) +      Provider.setup(this.state.domain).then( +        provider => { +          this.props.onClose(provider) +          // this.setState({working: false}) +        }, +        error => { +          this.setState({ +            validationState: 'warning', +            errorMsg: error, +            working: false +          }) +        } +      )      } -    this.props.onClose()    }    cancel() { @@ -44,9 +61,9 @@ class AddProviderModal extends React.Component {      let newMsg   = null      if (domain.length > 0) { -      let error = Validate.domain(domain) -      newState = error ? 'error' : 'success' -      newMsg   = error +      let msg = Validate.domain(domain) +      newState = msg ? 'error' : 'success' +      newMsg   = msg      }      this.setState({        domain: domain, @@ -57,11 +74,21 @@ class AddProviderModal extends React.Component {    render() {      let help = null +    let addButton = null      if (this.state.errorMsg) {        help = <HelpBlock>{this.state.errorMsg}</HelpBlock>      } else {        help = <HelpBlock> </HelpBlock>      } +    if (this.state.working) { +      addButton = <Button><Spinner /></Button> +    } else if (this.state.validationState == 'warning') { +      addButton = <Button onClick={this.accept}>Retry</Button> +    } else if (this.state.validationState == 'error') { +      addButton = <Button disabled={true}>Add</Button> +    } else { +      addButton = <Button onClick={this.accept}>Add</Button> +    }      let form = <form onSubmit={this.accept} autoComplete="off">        <FormGroup controlId="addprovider" validationState={this.state.validationState}>          <ControlLabel>Domain</ControlLabel> @@ -72,10 +99,12 @@ class AddProviderModal extends React.Component {            value={this.state.domain}            onChange={this.changed}            onBlur={this.changed} /> -        <FormControl.Feedback/>          {help}        </FormGroup> -      <Button onClick={this.accept}>Add</Button> +      <ButtonToolbar> +        {addButton} +        <Button onClick={this.cancel}>Cancel</Button> +      </ButtonToolbar>      </form>      return( @@ -90,5 +119,3 @@ class AddProviderModal extends React.Component {      )    }  } - -export default AddProviderModal
\ No newline at end of file diff --git a/ui/app/components/wizard/index.js b/ui/app/components/wizard/index.js index 613b88f..75e3a1d 100644 --- a/ui/app/components/wizard/index.js +++ b/ui/app/components/wizard/index.js @@ -6,26 +6,27 @@ import React from 'react'  import App from 'app'  import ProviderSelectStage from './provider_select_stage' +import RegisterStage from './register_stage'  import './wizard.less'  export default class Wizard extends React.Component { +  static get defaultProps() {return{ +    stage: "provider" +  }} +    constructor(props) {      super(props) -    this.state = { -      stage: 'provider' -    } -  } - -  setStage(stage) { -    this.setState({stage: stage})    }    render() {      let stage = null -    switch(this.state.stage) { +    switch(this.props.stage) {        case 'provider': -        stage = <ProviderSelectStage /> +        stage = <ProviderSelectStage {...this.props}/> +        break +      case 'register': +        stage = <RegisterStage {...this.props}/>          break      }      return( diff --git a/ui/app/components/wizard/provider_select_stage.js b/ui/app/components/wizard/provider_select_stage.js index 20674be..19799f8 100644 --- a/ui/app/components/wizard/provider_select_stage.js +++ b/ui/app/components/wizard/provider_select_stage.js @@ -2,7 +2,11 @@ import React from 'react'  import {Button, ButtonGroup, ButtonToolbar, Glyphicon} from 'react-bootstrap'  import App from 'app' -import ListEdit from 'components/list_edit' +import Provider from 'models/provider' + +import ListEditor from 'components/list_editor' +import {HorizontalLayout, Column} from 'components/layout' +  import StageLayout from './stage_layout'  import AddProviderModal from './add_provider_modal' @@ -10,75 +14,163 @@ export default class ProviderSelectStage extends React.Component {    static get defaultProps() {return{      title: "Choose a provider", -    subtitle: "This doesn't work yet" +    initialProvider: null    }}    constructor(props) {      super(props) -    let domains = this.currentDomains()      this.state = { -      domains: domains, -      showModal: false +      domains: [],        // array of domains, as strings +      showModal: false, +      selected: null,     // domain of selected item +      provider: null,     // Provider object, if selected +      error: null         // error message      } -    this.add = this.add.bind(this) -    this.remove = this.remove.bind(this) -    this.close = this.close.bind(this) -    this.previous = this.previous.bind(this) +    this.add      = this.add.bind(this) +    this.remove   = this.remove.bind(this) +    this.select   = this.select.bind(this) +    this.close    = this.close.bind(this) +    this.cancel   = this.cancel.bind(this) +    this.next     = this.next.bind(this) +  } + +  componentWillMount() { +    this.refreshList({ +      provider: this.props.initialProvider, +      selected: (this.props.initialProvider ? this.props.initialProvider.domain : null) +    })    } -  currentDomains() { -    // return(App.providers.domains().slice() || []) -    return ['domain1', 'domain2', 'domain3'] +  // +  // newState is the state to apply after +  // domains are refreshed +  // +  refreshList(newState=null) { +    Provider.list(true).then(domains => { +      this.setState(Object.assign({domains: domains}, newState)) +      if (domains.length > 0) { +        let domain = this.state.selected +        if (domains.includes(domain)) { +          this.select(domain) +        } else { +          this.select(domains[0]) +        } +      } else { +        this.select(null) +      } +    })    }    add() {      this.setState({showModal: true})    } -  remove(provider) { -    // App.providers.remove(provider) -    this.setState({domains: this.currentDomains()}) +  remove(domain, newactive) { +    Provider.delete(domain).then( +      response => { +        this.refreshList({selected: newactive}) +      }, +      error => { +        console.log(error) +      } +    )    } -  close() { -    let domains = this.currentDomains() -    if (domains.length != this.state.domains.length) { -      // this is ugly, but i could not get selection working -      // by passing it as a property -      this.refs.list.setSelected(0) -    } +  select(domain) {      this.setState({ -      domains: domains, -      showModal: false +      selected: domain      }) +    if (domain) { +      Provider.get(domain).then( +        provider => { +          this.setState({ +            provider: provider +          }) +        }, +        error => { +          this.setState({ +            provider: null, +            error: error +          }) +        } +      ) +    } else { +      this.setState({ +        provider: null, +        error: null +      }) +    } +  } + +  close(provider=null) { +    if (provider) { +      this.refreshList({ +        showModal: false, +        provider: provider, +        selected: provider.domain +      }) +    } else { +      this.setState({ +        showModal: false +      }) +    }    } -  previous() { +  cancel() {      App.start()    } +  next() { +    App.show('wizard', { +      stage: 'register', +      provider: this.state.provider +    }) +  } +    render() {      let modal = null +    let info = null +    if (this.state.provider) { +      info = ( +        <div> +          <h1 className="first">{this.state.provider.name}</h1> +          <h3>{this.state.provider.domain}</h3> +          <p>{this.state.provider.description}</p> +          <p><b>Enrollment Policy:</b> {this.state.provider.enrollment_policy}</p> +          <p><b>Services</b>: {this.state.provider.services}</p> +          <p><b>Languages</b>: {this.state.provider.languages.join(', ')}</p> +        </div> +      ) +    } else if (this.state.error) { +      info = <div>{this.state.error}</div> +    }      if (this.state.showModal) {        modal = <AddProviderModal onClose={this.close} />      }      let buttons = ( -      <ButtonToolbar className="pull-right"> -        <Button onClick={this.previous}> -          <Glyphicon glyph="chevron-left" /> -          Previous -        </Button> -        <Button> -          Next -          <Glyphicon glyph="chevron-right" /> -        </Button> -      </ButtonToolbar> +      <div> +        <ButtonToolbar className="pull-left"> +          <Button onClick={this.cancel}> +            Cancel +          </Button> +        </ButtonToolbar> +        <ButtonToolbar className="pull-right"> +          <Button onClick={this.next}> +            Next +            <Glyphicon glyph="chevron-right" /> +          </Button> +        </ButtonToolbar> +      </div>      ) -    let select = <ListEdit ref="list" items={this.state.domains} -      onRemove={this.remove} onAdd={this.add} /> +    let editlist = <ListEditor ref="list" items={this.state.domains} +      selected={this.state.selected} onRemove={this.remove} onAdd={this.add} +      onSelect={this.select} />      return(        <StageLayout title={this.props.title} subtitle={this.props.subtitle} buttons={buttons}> -        {select} +        <HorizontalLayout equalWidths={true}> +          <Column>{editlist}</Column> +          <Column>{info}</Column> +        </HorizontalLayout>          {modal}        </StageLayout>      ) diff --git a/ui/app/components/wizard/register_stage.js b/ui/app/components/wizard/register_stage.js new file mode 100644 index 0000000..9afa958 --- /dev/null +++ b/ui/app/components/wizard/register_stage.js @@ -0,0 +1,102 @@ +import React from 'react' +import {Button, ButtonGroup, ButtonToolbar, +        Glyphicon, Tabs, Tab} from 'react-bootstrap' + +import App from 'app' +import Provider from 'models/provider' +import Login from 'components/login' +import Center from 'components/center' + +import StageLayout from './stage_layout' + +export default class RegisterStage extends React.Component { + +  static get defaultProps() {return{ +    provider: null +  }} + +  constructor(props) { +    super(props) +    this.state = { +      activeTab:   'signup',   // either 'login' or 'signup' +      error: null       // error message +    } +    // this.add      = this.add.bind(this) +    // this.remove   = this.remove.bind(this) +    // this.select   = this.select.bind(this) +    this.selectTab = this.selectTab.bind(this) +    this.previous = this.previous.bind(this) +    this.cancel = this.cancel.bind(this) +    this.login = this.login.bind(this) +  } + +  previous() { +    App.show('wizard', { +      stage: 'provider', +      initialProvider: this.props.provider +    }) +  } + +  cancel() { +    App.start() +  } + +  login(account) { +    App.show('main', {initialAccount: account}) +  } + +  selectTab(key) { +    this.setState({ +      activeTab: key +    }) +  } + +  render() { +    let info = null +    if (this.props.provider) { +      info = ( +        <div> +          <h1 className="first">{this.props.provider.name}</h1> +          <h3>{this.props.provider.domain}</h3> +          <p>{this.props.provider.description}</p> +          <p><b>Enrollment Policy:</b> {this.props.provider.enrollment_policy}</p> +          <p><b>Services</b>: {this.props.provider.services}</p> +          <p><b>Languages</b>: {this.props.provider.languages.join(', ')}</p> +        </div> +      ) +    } +    let buttons = ( +      <div> +        <ButtonToolbar className="pull-left"> +          <Button onClick={this.cancel}> +            Cancel +          </Button> +        </ButtonToolbar> +        <ButtonToolbar className="pull-right"> +          <Button onClick={this.previous}> +            <Glyphicon glyph="chevron-left" /> +            Previous +          </Button> +        </ButtonToolbar> +      </div> +    ) +    return( +      <StageLayout title={this.props.provider.domain} buttons={buttons}> +        <Tabs activeKey={this.state.activeTab} onSelect={this.selectTab} animation={false} id="login-tabs"> +          <Tab eventKey="signup" title="Sign up"> +            <div className="vspacer" /> +            <Center direction="horizontal" width={400}> +              <Login mode="signup" domain={this.props.provider.domain} onLogin={this.login} /> +            </Center> +          </Tab> +          <Tab eventKey="login" title="Log In"> +            <div className="vspacer" /> +            <Center direction="horizontal" width={400}> +              <Login domain={this.props.provider.domain} onLogin={this.login} /> +            </Center> +          </Tab> +        </Tabs> +      </StageLayout> +    ) +  } +} | 
