Skip to content

Commit

Permalink
Add option to render Wizard in horizontal (Graylog2#4853)
Browse files Browse the repository at this point in the history
Sometimes we want to provide a wizard having some extra width for rendering components, e.g. when rendering a wizard inside a modal. In these cases, it is good rendering our `Wizard` component in horizontal, allowing us to save some space. This PR adds support for that.

Additionally, I also added a change, making the `content` CSS class in the outer row of the `Wizard` component customisable, as we may not always want to draw a border around the wizard.
  • Loading branch information
edmundoa authored and bernd committed Jun 20, 2018
1 parent 060bd15 commit 515c802
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 21 deletions.
8 changes: 8 additions & 0 deletions graylog2-web-interface/src/components/common/Wizard.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
:local(.subnavigation) {
border-right: #D1D1D1 solid 1px;
}

:local(.horizontal) {
margin-bottom: 15px;
}

:local(.horizontalPreviousNextButtons) {
padding: 7px;
}
73 changes: 54 additions & 19 deletions graylog2-web-interface/src/components/common/Wizard.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';

import { Row, Button, Col, Nav, NavItem } from 'react-bootstrap';
import { Button, ButtonToolbar, Col, Nav, NavItem, Row } from 'react-bootstrap';

import WizardStyle from './Wizard.css';

Expand Down Expand Up @@ -33,11 +33,17 @@ class Wizard extends React.Component {
onStepChange: PropTypes.func,
/** Optional component which can be rendered on the right side e.g a preview */
children: PropTypes.element,
/** Indicates if wizard should be rendered in horizontal or vertical */
horizontal: PropTypes.bool,
/** Customize the container CSS class used by this component */
containerClassName: PropTypes.string,
};

static defaultProps = {
children: undefined,
onStepChange: () => {},
horizontal: false,
containerClassName: 'content',
};

constructor(props) {
Expand Down Expand Up @@ -71,30 +77,59 @@ class Wizard extends React.Component {
return this.props.steps.map(step => step.key).indexOf(this.state.selectedStep);
};

_renderVerticalStepNav = () => {
return (
<Col md={2} className={WizardStyle.subnavigation}>
<Nav stacked bsStyle="pills" activeKey={this.state.selectedStep} onSelect={this._wizardChanged}>
{this.props.steps.map((navItem) => {
return (<NavItem key={navItem.key} eventKey={navItem.key}>{navItem.title}</NavItem>);
})}
</Nav>
<br />
<Row>
<Col xs={6}>
<Button onClick={this._onPrevious} bsSize="small" bsStyle="info" disabled={this._disableButton('previous')}>Previous</Button>
</Col>
<Col className="text-right" xs={6}>
<Button onClick={this._onNext} bsSize="small" bsStyle="info" disabled={this._disableButton('next')}>Next</Button>
</Col>
</Row>
</Col>
);
};

_renderHorizontalStepNav = () => {
return (
<Col sm={12} className={WizardStyle.horizontal}>
<div className="pull-right">
<ButtonToolbar className={WizardStyle.horizontalPreviousNextButtons}>
<Button onClick={this._onPrevious} bsSize="xsmall" bsStyle="info" disabled={this._disableButton('previous')}>
<i className="fa fa-caret-left" />
</Button>
<Button onClick={this._onNext} bsSize="xsmall" bsStyle="info" disabled={this._disableButton('next')}>
<i className="fa fa-caret-right" />
</Button>
</ButtonToolbar>
</div>
<Nav bsStyle="pills" activeKey={this.state.selectedStep} onSelect={this._wizardChanged}>
{this.props.steps.map((navItem) => {
return (<NavItem key={navItem.key} eventKey={navItem.key}>{navItem.title}</NavItem>);
})}
</Nav>
</Col>
);
};

render() {
const rightComponentCols = this.props.horizontal ? 5 : 3; // If horizontal, use more space for this component
return (
<Row className="content">
<Col md={2} className={WizardStyle.subnavigation}>
<Nav stacked bsStyle="pills" activeKey={this.state.selectedStep} onSelect={this._wizardChanged}>
{this.props.steps.map((navItem) => {
return (<NavItem key={navItem.key} eventKey={navItem.key}>{navItem.title}</NavItem>);
})}
</Nav>
<br />
<Row>
<Col xs={6}>
<Button onClick={this._onPrevious} bsSize="small" bsStyle="info" disabled={this._disableButton('previous')}>Previous</Button>
</Col>
<Col className="text-right" xs={6}>
<Button onClick={this._onNext} bsSize="small" bsStyle="info" disabled={this._disableButton('next')}>Next</Button>
</Col>
</Row>
</Col>
<Row className={this.props.containerClassName}>
{this.props.horizontal ? this._renderHorizontalStepNav() : this._renderVerticalStepNav()}
<Col md={7}>
{this.props.steps[this._getSelectedIndex()].component}
</Col>
{this.props.children &&
<Col md={3}>
<Col md={rightComponentCols}>
{this.props.children}
</Col>
}
Expand Down
8 changes: 6 additions & 2 deletions graylog2-web-interface/src/components/common/Wizard.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ const WizardExample = createReactClass({
];

return (
<Wizard steps={steps}>
<Wizard steps={steps} horizontal={this.props.horizontal}>
<div>Preview: {this.state.input_value}</div>
</Wizard>
);
},
});

<WizardExample />
<div>
<WizardExample horizontal={false} />
<hr/>
<WizardExample horizontal />
</div>

```
10 changes: 10 additions & 0 deletions graylog2-web-interface/src/components/common/Wizard.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ describe('<Wizard />', () => {
expect(wrapper.toJSON()).toMatchSnapshot();
});

it('should render in horizontal mode with 3 steps', () => {
const wrapper = renderer.create(<Wizard steps={steps} horizontal />);
expect(wrapper.toJSON()).toMatchSnapshot();
});

it('should render in horizontal mode with 3 steps and children', () => {
const wrapper = renderer.create(<Wizard steps={steps} horizontal><span>Preview</span></Wizard>);
expect(wrapper.toJSON()).toMatchSnapshot();
});

it('should render step 1 when nothing was clicked', () => {
const wrapper = mount(<Wizard steps={steps} />);
expect(wrapper.find('div[children="Component1"]').exists()).toBe(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,200 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Wizard /> should render in horizontal mode with 3 steps 1`] = `
<div
className="content row"
>
<div
className="horizontal col-sm-12"
>
<div
className="pull-right"
>
<div
className="horizontalPreviousNextButtons btn-toolbar"
role="toolbar"
>
<button
className="btn btn-xs btn-info"
disabled={true}
onClick={[Function]}
type="button"
>
<i
className="fa fa-caret-left"
/>
</button>
<button
className="btn btn-xs btn-info"
disabled={false}
onClick={[Function]}
type="button"
>
<i
className="fa fa-caret-right"
/>
</button>
</div>
</div>
<ul
className="nav nav-pills"
role={null}
>
<li
className="active"
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title1
</a>
</li>
<li
className=""
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title2
</a>
</li>
<li
className=""
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title3
</a>
</li>
</ul>
</div>
<div
className="col-md-7"
>
<div>
Component1
</div>
</div>
</div>
`;

exports[`<Wizard /> should render in horizontal mode with 3 steps and children 1`] = `
<div
className="content row"
>
<div
className="horizontal col-sm-12"
>
<div
className="pull-right"
>
<div
className="horizontalPreviousNextButtons btn-toolbar"
role="toolbar"
>
<button
className="btn btn-xs btn-info"
disabled={true}
onClick={[Function]}
type="button"
>
<i
className="fa fa-caret-left"
/>
</button>
<button
className="btn btn-xs btn-info"
disabled={false}
onClick={[Function]}
type="button"
>
<i
className="fa fa-caret-right"
/>
</button>
</div>
</div>
<ul
className="nav nav-pills"
role={null}
>
<li
className="active"
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title1
</a>
</li>
<li
className=""
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title2
</a>
</li>
<li
className=""
role="presentation"
style={undefined}
>
<a
href="#"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
>
Title3
</a>
</li>
</ul>
</div>
<div
className="col-md-7"
>
<div>
Component1
</div>
</div>
<div
className="col-md-5"
>
<span>
Preview
</span>
</div>
</div>
`;

exports[`<Wizard /> should render with 3 steps 1`] = `
<div
className="content row"
Expand Down

0 comments on commit 515c802

Please sign in to comment.