Skip to content

Commit

Permalink
Merge pull request #64 from glific/feature/wait-for-result
Browse files Browse the repository at this point in the history
Added wait for result node
  • Loading branch information
pankaj-ag authored Jan 5, 2022
2 parents b708058 + 71676b8 commit f82ae24
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/components/flow/actions/action/Action.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
&.missing,
&.wait_for_time,
&.send_interactive_msg,
&.wait_for_result,
&.enter_flow {
width: $node_min_width - $action_padding * 2;
padding: $action_padding;
Expand Down
26 changes: 26 additions & 0 deletions src/components/flow/routers/webhookresult/WebhookResultRouter.tsx
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;
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 src/components/flow/routers/webhookresult/WebhookResultRouterForm.tsx
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();
}
}
72 changes: 72 additions & 0 deletions src/components/flow/routers/webhookresult/helpers.ts
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;
};
4 changes: 4 additions & 0 deletions src/components/shared.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
background: $dark_blue;
}

.wait_for_result {
background: $hawaiian-tan;
}

.wait_for_time {
background: $mongoose;
}
Expand Down
1 change: 1 addition & 0 deletions src/config/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export enum Types {
wait_for_video = 'wait_for_video',
wait_for_location = 'wait_for_location',
wait_for_image = 'wait_for_image',
wait_for_result = 'wait_for_result',
missing = 'missing',
say_msg = 'say_msg',
play_audio = 'play_audio'
Expand Down
9 changes: 9 additions & 0 deletions src/config/typeConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ import OpenTicketComp from 'components/flow/actions/openticket/OpenTicket';
import SequenceForm from 'components/flow/routers/sequence/SequenceForm';
import Sequence from 'components/flow/routers/sequence/Sequence';
import SendInteractiveMsgComp from 'components/flow/actions/sendinteractivemsg/SendInteractiveMsg';
import WebhookResultRouterForm from 'components/flow/routers/webhookresult/WebhookResultRouterForm';
import WebhookResultRouter from 'components/flow/routers/webhookresult/WebhookResultRouter';

const dedupeTypeConfigs = (typeConfigs: Type[]) => {
const map: any = {};
Expand Down Expand Up @@ -432,6 +434,13 @@ export const typeConfigList: Type[] = [
localizeableKeys: ['exits'],
visibility: VISIBILITY_SURVEYOR
},
{
type: Types.wait_for_result,
name: i18n.t('actions.wait_for_result.name', 'Wait for result'),
description: i18n.t('actions.wait_for_result.description', 'Wait for result'),
form: WebhookResultRouterForm,
component: WebhookResultRouter
},
{
type: Types.wait_for_video,
name: i18n.t('actions.wait_for_video.name', 'Wait for Video'),
Expand Down
1 change: 1 addition & 0 deletions src/variables.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ $light_gray: #e6e6e6;
$light_gray_2: lighten($light_gray, 5%);
$dark_gray: #aaa;
$med_gray: #ccc;
$hawaiian-tan: #a05b18;

// specific color styling
$node_shadow: 4px 4px 0px 0px;
Expand Down

0 comments on commit f82ae24

Please sign in to comment.