Add navigation ability to wizard buttons, close wizard on final
Co-authored-by: Daniel Campbell <metalwhirlwind@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com>generic-wizard
parent
d14a9f4dac
commit
0e22181190
|
@ -1,11 +1,14 @@
|
|||
import React, {PureComponent, ReactElement, ReactNode} from 'react'
|
||||
import WizardProgressBar from 'src/reusable_ui/components/wizard/WizardProgressBar'
|
||||
import WizardStep from 'src/reusable_ui/components/wizard/WizardStep'
|
||||
|
||||
interface WizardStepProps {
|
||||
children: ReactNode
|
||||
title: string
|
||||
isComplete: () => boolean
|
||||
onPrevious: () => void
|
||||
onNext: () => void
|
||||
increment?: () => void
|
||||
decrement?: () => void
|
||||
}
|
||||
|
||||
enum StepStatus {
|
||||
|
@ -25,12 +28,13 @@ interface State {
|
|||
}
|
||||
|
||||
interface Props {
|
||||
children: ReactElement<WizardStep>
|
||||
children: Array<ReactElement<WizardStepProps>>
|
||||
toggleVisibility: (isVisible: boolean) => () => void
|
||||
}
|
||||
|
||||
class WizardCloak extends PureComponent<Props, State> {
|
||||
public static getDerivedStateFromProps(props: Props) {
|
||||
let currentStepIndex = -1
|
||||
public static getDerivedStateFromProps(props: Props, state: State) {
|
||||
let {currentStepIndex} = state
|
||||
const childSteps = React.Children.map(
|
||||
props.children,
|
||||
(child: ReactElement<WizardStepProps>, i) => {
|
||||
|
@ -50,6 +54,14 @@ class WizardCloak extends PureComponent<Props, State> {
|
|||
return {steps: childSteps, currentStepIndex}
|
||||
}
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
steps: [],
|
||||
currentStepIndex: -1,
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {steps, currentStepIndex} = this.state
|
||||
|
||||
|
@ -61,11 +73,37 @@ class WizardCloak extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get CurrentChild(): JSX.Element {
|
||||
const {children} = this.props
|
||||
private incrementStep = () => {
|
||||
const {currentStepIndex} = this.state
|
||||
|
||||
return children[currentStepIndex]
|
||||
this.setState({
|
||||
currentStepIndex: currentStepIndex + 1,
|
||||
})
|
||||
}
|
||||
|
||||
private decrementStep = () => {
|
||||
const {currentStepIndex} = this.state
|
||||
|
||||
this.setState({
|
||||
currentStepIndex: currentStepIndex - 1,
|
||||
})
|
||||
}
|
||||
|
||||
private get CurrentChild(): JSX.Element {
|
||||
const {children, toggleVisibility} = this.props
|
||||
const {currentStepIndex, steps} = this.state
|
||||
|
||||
const advance =
|
||||
currentStepIndex === steps.length - 1
|
||||
? toggleVisibility(false)
|
||||
: this.incrementStep
|
||||
|
||||
const retreat = currentStepIndex === 0 ? null : this.decrementStep
|
||||
|
||||
return React.cloneElement<WizardStepProps>(children[currentStepIndex], {
|
||||
increment: advance,
|
||||
decrement: retreat,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,39 @@
|
|||
import React, {PureComponent, ReactNode} from 'react'
|
||||
import React, {PureComponent, ReactElement, ReactNode} from 'react'
|
||||
import OverlayBody from 'src/reusable_ui/components/overlays/OverlayBody'
|
||||
import OverlayContainer from 'src/reusable_ui/components/overlays/OverlayContainer'
|
||||
import OverlayTechnology from 'src/reusable_ui/components/overlays/OverlayTechnology'
|
||||
import WizardCloak from 'src/reusable_ui/components/wizard/WizardCloak'
|
||||
import OverlayHeading from 'src/reusable_ui/components/overlays/OverlayHeading'
|
||||
|
||||
interface WizardStepProps {
|
||||
children: ReactNode
|
||||
title: string
|
||||
isComplete: () => boolean
|
||||
onPrevious: () => void
|
||||
onNext: () => void
|
||||
increment?: () => void
|
||||
decrement?: () => void
|
||||
}
|
||||
// import {} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
children: ReactNode
|
||||
children: Array<ReactElement<WizardStepProps>>
|
||||
visible: boolean
|
||||
title: string
|
||||
toggleVisibility: (isVisible: boolean) => () => void
|
||||
}
|
||||
|
||||
class WizardOverlay extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {children, visible, title} = this.props
|
||||
const {children, visible, title, toggleVisibility} = this.props
|
||||
|
||||
return (
|
||||
<OverlayTechnology visible={visible}>
|
||||
<OverlayContainer>
|
||||
<OverlayHeading title={title} />
|
||||
<OverlayBody>
|
||||
<WizardCloak>{children}</WizardCloak>
|
||||
<WizardCloak toggleVisibility={toggleVisibility}>
|
||||
{children}
|
||||
</WizardCloak>
|
||||
</OverlayBody>
|
||||
</OverlayContainer>
|
||||
</OverlayTechnology>
|
||||
|
|
|
@ -10,27 +10,49 @@ interface Props {
|
|||
isComplete: () => boolean
|
||||
onPrevious: () => void
|
||||
onNext: () => void
|
||||
increment?: () => void
|
||||
decrement?: () => void
|
||||
}
|
||||
|
||||
class WizardStep extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {children, title, onPrevious, onNext} = this.props
|
||||
const {children, title, decrement} = this.props
|
||||
|
||||
return (
|
||||
<div className="progress-step">
|
||||
<h2>{title}</h2>
|
||||
{children}
|
||||
<div className="button-bar">
|
||||
<button className="btn btn-md btn-default" onClick={onPrevious}>
|
||||
Alakazam
|
||||
</button>
|
||||
<button className="btn btn-md btn-primary" onClick={onNext}>
|
||||
{decrement && (
|
||||
<button
|
||||
className="btn btn-md btn-default"
|
||||
onClick={this.handleClickPrevious}
|
||||
>
|
||||
Alakazam
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="btn btn-md btn-primary"
|
||||
onClick={this.handleClickNext}
|
||||
>
|
||||
Abrakabra
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private handleClickPrevious = () => {
|
||||
const {onPrevious, decrement} = this.props
|
||||
onPrevious() // TODO wait if async function
|
||||
decrement()
|
||||
}
|
||||
|
||||
private handleClickNext = () => {
|
||||
const {onNext, increment} = this.props
|
||||
onNext()
|
||||
increment()
|
||||
}
|
||||
}
|
||||
|
||||
export default WizardStep
|
||||
|
|
|
@ -6,6 +6,7 @@ import WizardStep from 'src/reusable_ui/components/wizard/WizardStep'
|
|||
|
||||
interface Props {
|
||||
wizardVisibility: boolean
|
||||
toggleVisibility: (isVisible: boolean) => () => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -13,24 +14,29 @@ interface State {
|
|||
}
|
||||
|
||||
class WizardWithSteps extends PureComponent<Props, State> {
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
completion: {
|
||||
first: false,
|
||||
first: true,
|
||||
second: false,
|
||||
third: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
public render() {
|
||||
const {wizardVisibility} = this.props
|
||||
|
||||
const {wizardVisibility, toggleVisibility} = this.props
|
||||
return (
|
||||
<WizardOverlay visible={wizardVisibility} title="Grand Wizard">
|
||||
<WizardOverlay
|
||||
visible={wizardVisibility}
|
||||
toggleVisibility={toggleVisibility}
|
||||
title="Grand Wizard"
|
||||
>
|
||||
<WizardStep
|
||||
title="First Real Step"
|
||||
isComplete={this.completeTest('first')}
|
||||
onNext={this.handleFirstNext}
|
||||
onPrevious={this.handleFirstPrev}
|
||||
>
|
||||
some first children
|
||||
</WizardStep>
|
||||
|
@ -38,6 +44,7 @@ class WizardWithSteps extends PureComponent<Props, State> {
|
|||
title="Second Real Step"
|
||||
isComplete={this.completeTest('second')}
|
||||
onNext={this.handleSecondNext}
|
||||
onPrevious={this.handleSecondPrev}
|
||||
>
|
||||
some second children
|
||||
</WizardStep>
|
||||
|
@ -45,6 +52,7 @@ class WizardWithSteps extends PureComponent<Props, State> {
|
|||
title="Third Real Step"
|
||||
isComplete={this.completeTest('third')}
|
||||
onNext={this.handleThirdNext}
|
||||
onPrevious={this.handleThirdPrev}
|
||||
>
|
||||
some third children
|
||||
</WizardStep>
|
||||
|
@ -57,6 +65,13 @@ class WizardWithSteps extends PureComponent<Props, State> {
|
|||
return completion[curr]
|
||||
}
|
||||
|
||||
private handleFirstNext = () => {
|
||||
const {completion} = this.state
|
||||
this.setState({
|
||||
completion: {...completion, first: true},
|
||||
})
|
||||
}
|
||||
|
||||
private handleSecondNext = () => {
|
||||
const {completion} = this.state
|
||||
this.setState({
|
||||
|
@ -70,6 +85,27 @@ class WizardWithSteps extends PureComponent<Props, State> {
|
|||
completion: {...completion, third: true},
|
||||
})
|
||||
}
|
||||
|
||||
private handleFirstPrev = () => {
|
||||
const {completion} = this.state
|
||||
this.setState({
|
||||
completion: {...completion, first: false},
|
||||
})
|
||||
}
|
||||
|
||||
private handleSecondPrev = () => {
|
||||
const {completion} = this.state
|
||||
this.setState({
|
||||
completion: {...completion, second: false},
|
||||
})
|
||||
}
|
||||
|
||||
private handleThirdPrev = () => {
|
||||
const {completion} = this.state
|
||||
this.setState({
|
||||
completion: {...completion, third: false},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default WizardWithSteps
|
||||
|
|
|
@ -78,7 +78,10 @@ class ManageSources extends PureComponent<Props, State> {
|
|||
<p className="version-number">Chronograf Version: {VERSION}</p>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
<GrandWizard wizardVisibility={wizardVisibility} />
|
||||
<GrandWizard
|
||||
wizardVisibility={wizardVisibility}
|
||||
toggleVisibility={this.toggleVisibility}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue