forked from nyaruka/floweditor
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from glific/feature/wait-for-result
Added wait for result node
- Loading branch information
Showing
9 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/components/flow/routers/webhookresult/WebhookResultRouter.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import * as React from 'react'; | ||
|
||
import { Delay } from 'flowTypes'; | ||
|
||
const wordsBasedOnTime = (time: number, type: string) => { | ||
return time > 0 ? time + (time > 1 ? ` ${type}s ` : ` ${type} `) : ''; | ||
}; | ||
|
||
const WebhookResultRouter: React.SFC<Delay> = (action: Delay): JSX.Element => { | ||
const delayInSeconds = parseInt(action.delay ? action.delay : '0'); | ||
|
||
const days = Math.floor(delayInSeconds / (3600 * 24)); | ||
const noOfDays = wordsBasedOnTime(days, 'day'); | ||
|
||
const hours = Math.floor((delayInSeconds % (3600 * 24)) / 3600); | ||
const noOfHours = wordsBasedOnTime(hours, 'hour'); | ||
|
||
const minutes = Math.floor((delayInSeconds % 3600) / 60); | ||
const noOfMinutes = wordsBasedOnTime(minutes, 'minute'); | ||
|
||
const waitForTime = `Waiting for ${noOfDays} ${noOfHours} ${noOfMinutes}`; | ||
|
||
return <div>{waitForTime}</div>; | ||
}; | ||
|
||
export default WebhookResultRouter; |
21 changes: 21 additions & 0 deletions
21
src/components/flow/routers/webhookresult/WebhookResultRouterForm.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
.title { | ||
margin: 5px; | ||
font-size: 9px; | ||
} | ||
|
||
.result_container { | ||
display: flex; | ||
margin-top: 10px; | ||
align-items: center; | ||
} | ||
|
||
.input { | ||
padding: 10px 20px; | ||
display: block; | ||
} | ||
|
||
.error { | ||
font-size: 12px; | ||
margin-left: 20px; | ||
color: red; | ||
} |
138 changes: 138 additions & 0 deletions
138
src/components/flow/routers/webhookresult/WebhookResultRouterForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { react as bindCallbacks } from 'auto-bind'; | ||
import Dialog, { ButtonSet } from 'components/dialog/Dialog'; | ||
import { hasErrors } from 'components/flow/actions/helpers'; | ||
import { RouterFormProps } from 'components/flow/props'; | ||
import TypeList from 'components/nodeeditor/TypeList'; | ||
import * as React from 'react'; | ||
import { FormState, StringEntry } from 'store/nodeEditor'; | ||
import { Numeric, Required, validate } from 'store/validators'; | ||
|
||
import { nodeToState, stateToNode } from './helpers'; | ||
import styles from './WebhookResultRouterForm.module.scss'; | ||
import i18n from 'config/i18n'; | ||
import TextInputElement, { TextInputStyle } from 'components/form/textinput/TextInputElement'; | ||
|
||
export interface WebhookResultRouterFormState extends FormState { | ||
days: StringEntry; | ||
hours: StringEntry; | ||
minutes: StringEntry; | ||
} | ||
|
||
export default class WebhookResultRouterForm extends React.Component< | ||
RouterFormProps, | ||
WebhookResultRouterFormState | ||
> { | ||
constructor(props: RouterFormProps) { | ||
super(props); | ||
|
||
this.state = nodeToState(this.props.nodeSettings); | ||
|
||
bindCallbacks(this, { | ||
include: [/^on/, /^handle/] | ||
}); | ||
} | ||
|
||
private handleDaysChange(value: string): void { | ||
const days = validate(i18n.t('forms.save_days', 'Days'), value, [Numeric, Required]); | ||
this.setState({ | ||
days | ||
}); | ||
} | ||
private handleMinutesChange(value: string): void { | ||
const minutes = validate(i18n.t('forms.save_minutes', 'Minutes'), value, [Numeric, Required]); | ||
this.setState({ | ||
minutes | ||
}); | ||
} | ||
|
||
private handleHoursChange(value: string): void { | ||
const hours = validate(i18n.t('forms.save_hours', 'Hours'), value, [Numeric, Required]); | ||
this.setState({ | ||
hours | ||
}); | ||
} | ||
|
||
private handleSave(): void { | ||
let valid = false; | ||
const minutes = validate(i18n.t('forms.save_minutes', 'Minutes'), this.state.minutes.value, [ | ||
Numeric | ||
]); | ||
const hours = validate(i18n.t('forms.save_hours', 'Hours'), this.state.hours.value, [Numeric]); | ||
const days = validate(i18n.t('forms.save_days', 'Days'), this.state.days.value, [Numeric]); | ||
|
||
if (!hasErrors(minutes) && !hasErrors(hours) && !hasErrors(days)) { | ||
valid = true; | ||
} | ||
|
||
const delayInSeconds = | ||
parseInt(days.value) * 86400 + parseInt(hours.value) * 3600 + parseInt(minutes.value) * 60; | ||
if (delayInSeconds === 0) { | ||
valid = false; | ||
this.setState({ | ||
valid: false | ||
}); | ||
} | ||
|
||
if (valid) { | ||
this.props.updateRouter(stateToNode(this.props.nodeSettings, this.state)); | ||
this.props.onClose(false); | ||
} | ||
} | ||
|
||
private getButtons(): ButtonSet { | ||
return { | ||
primary: { name: i18n.t('buttons.ok', 'Ok'), onClick: this.handleSave }, | ||
secondary: { | ||
name: i18n.t('buttons.cancel', 'Cancel'), | ||
onClick: () => this.props.onClose(true) | ||
} | ||
}; | ||
} | ||
|
||
public renderEdit(): JSX.Element { | ||
const typeConfig = this.props.typeConfig; | ||
|
||
return ( | ||
<Dialog title={typeConfig.name} headerClass={typeConfig.type} buttons={this.getButtons()}> | ||
<TypeList __className="" initialType={typeConfig} onChange={this.props.onTypeChange} /> | ||
|
||
<div className={styles.result_container}> | ||
<div className={styles.input}> | ||
<span className={styles.title}>Days</span> | ||
<TextInputElement | ||
name={i18n.t('forms.save_days', 'Days')} | ||
placeholder="Enter days" | ||
onChange={this.handleDaysChange} | ||
style={TextInputStyle.small} | ||
entry={this.state.days} | ||
/> | ||
</div> | ||
<div className={styles.input}> | ||
<span className={styles.title}>Hours</span> | ||
<TextInputElement | ||
name={i18n.t('forms.save_hours', 'Hours')} | ||
placeholder="Enter hours" | ||
onChange={this.handleHoursChange} | ||
style={TextInputStyle.small} | ||
entry={this.state.hours} | ||
/> | ||
</div> | ||
<div className={styles.input}> | ||
<span className={styles.title}>Minutes</span> | ||
<TextInputElement | ||
name={i18n.t('forms.save_minutes', 'Minutes')} | ||
placeholder="Enter minutes" | ||
onChange={this.handleMinutesChange} | ||
style={TextInputStyle.small} | ||
entry={this.state.minutes} | ||
/> | ||
</div> | ||
</div> | ||
</Dialog> | ||
); | ||
} | ||
|
||
public render(): JSX.Element { | ||
return this.renderEdit(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { getActionUUID } from 'components/flow/actions/helpers'; | ||
import { createRenderNode, resolveRoutes } from 'components/flow/routers/helpers'; | ||
import {} from 'components/flow/routers/wait/WaitRouterForm'; | ||
import { DEFAULT_OPERAND } from 'components/nodeeditor/constants'; | ||
import { Types } from 'config/interfaces'; | ||
import { Delay, RouterTypes, SwitchRouter } from 'flowTypes'; | ||
import { RenderNode } from 'store/flowContext'; | ||
import { NodeEditorSettings } from 'store/nodeEditor'; | ||
import { WebhookResultRouterFormState } from './WebhookResultRouterForm'; | ||
|
||
export const nodeToState = (settings: NodeEditorSettings): WebhookResultRouterFormState => { | ||
let resulNode: WebhookResultRouterFormState = { | ||
valid: true, | ||
days: { value: '0' }, | ||
hours: { value: '0' }, | ||
minutes: { value: '1' } | ||
}; | ||
|
||
if (settings.originalAction && settings.originalAction.type === Types.wait_for_result) { | ||
const action = settings.originalAction as Delay; | ||
|
||
if (action.delay) { | ||
const delayInSeconds = parseInt(action.delay); | ||
resulNode.days.value = Math.floor(delayInSeconds / (3600 * 24)).toString(); | ||
resulNode.hours.value = Math.floor((delayInSeconds % (3600 * 24)) / 3600).toString(); | ||
resulNode.minutes.value = Math.floor((delayInSeconds % 3600) / 60).toString(); | ||
} | ||
} | ||
|
||
return resulNode; | ||
}; | ||
|
||
export const stateToNode = ( | ||
settings: NodeEditorSettings, | ||
state: WebhookResultRouterFormState | ||
): RenderNode => { | ||
const { days, hours, minutes } = state; | ||
|
||
const delayInSeconds = | ||
parseInt(days.value) * 86400 + parseInt(hours.value) * 3600 + parseInt(minutes.value) * 60; | ||
const { cases, exits, defaultCategory, caseConfig, categories } = resolveRoutes( | ||
[], | ||
false, | ||
settings.originalNode.node, | ||
'Completed' | ||
); | ||
|
||
const router: SwitchRouter = { | ||
type: RouterTypes.switch, | ||
default_category_uuid: defaultCategory, | ||
cases, | ||
categories, | ||
operand: DEFAULT_OPERAND | ||
}; | ||
|
||
const newRenderNode = createRenderNode( | ||
settings.originalNode.node.uuid, | ||
router, | ||
exits, | ||
Types.wait_for_result, | ||
[ | ||
{ | ||
type: Types.wait_for_result, | ||
uuid: getActionUUID(settings, Types.wait_for_result), | ||
delay: delayInSeconds.toString() | ||
} | ||
], | ||
{ cases: caseConfig } | ||
); | ||
|
||
return newRenderNode; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters