diff options
author | elijah <elijah@riseup.net> | 2016-09-21 15:39:03 -0700 |
---|---|---|
committer | Kali Kaneko (leap communications) <kali@leap.se> | 2016-09-22 11:40:14 -0400 |
commit | 7569ac8bd58174095f3f897548e26d0ba905236c (patch) | |
tree | 839c300d7dff62900bcc91672a3b55cf62c31f6c /ui/app/components/wizard | |
parent | 61b5734c12d6ab6733d3a832df8d99f1041bf355 (diff) |
[feat] the setup wizard for the new ui
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 bc5e0236..d54ec085 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 613b88fd..75e3a1d8 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 20674be1..19799f86 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 00000000..9afa9587 --- /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> + ) + } +} |