Skip to content

Commit

Permalink
Merge pull request #67 from glific/feature/interactive-message-lazy
Browse files Browse the repository at this point in the history
Added lazy loading for interactive message
  • Loading branch information
mdshamoon authored Mar 29, 2022
2 parents 762e7af + 9546bf5 commit 44eb466
Show file tree
Hide file tree
Showing 17 changed files with 187 additions and 50 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@glific/flow-editor",
"license": "AGPL-3.0",
"repository": "git://github.com/glific/floweditor.git",
"version": "1.17.0-2",
"version": "1.17.0-3",
"description": "'Standalone flow editing tool designed for use within the Glific suite of messaging tools'",
"browser": "umd/flow-editor.min.js",
"unpkg": "umd/flow-editor.min.js",
Expand Down
3 changes: 2 additions & 1 deletion src/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface DialogProps {
noPadding?: boolean;
tabs?: Tab[];
className?: string;
defaultTab?: number;
}

export interface DialogState {
Expand All @@ -57,7 +58,7 @@ export default class Dialog extends React.Component<DialogProps, DialogState> {
constructor(props: DialogProps) {
super(props);
this.state = {
activeTab: -1
activeTab: this.props.defaultTab !== null ? this.props.defaultTab : -1
};

bindCallbacks(this, {
Expand Down
12 changes: 8 additions & 4 deletions src/components/flow/actions/action/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ export class ActionWrapper extends React.Component<ActionWrapperProps> {
if (
this.props.action.type === Types.send_msg ||
this.props.action.type === Types.send_broadcast ||
this.props.action.type === Types.say_msg
this.props.action.type === Types.say_msg ||
this.props.action.type === Types.send_interactive_msg
) {
localizedKeys.push('text');
}
Expand Down Expand Up @@ -178,9 +179,12 @@ export class ActionWrapper extends React.Component<ActionWrapperProps> {
titleBarClass = shared.missing;
}

const events = this.context.config.mutable
? createClickHandler(this.handleActionClicked, () => this.props.selected)
: {};
const isInteractive =
this.props.translating && this.props.action.type === Types.send_interactive_msg;
const events =
this.context.config.mutable && !isInteractive
? createClickHandler(this.handleActionClicked, () => this.props.selected)
: {};

const body = (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ export default class SendBroadcastForm extends React.Component<
headerClass={typeConfig.type}
buttons={this.getButtons()}
tabs={[templates, attachments]}
defaultTab={0}
>
<TypeList __className="" initialType={typeConfig} onChange={this.props.onTypeChange} />
<AssetSelector
Expand Down
108 changes: 83 additions & 25 deletions src/components/flow/actions/sendinteractivemsg/SendInteractiveMsg.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,73 @@
import { SendInteractiveMsg } from 'flowTypes';
import * as React from 'react';
import React, { useEffect, useState } from 'react';

import i18n from 'config/i18n';
import { getMsgBody } from './helpers';
import { getHeader, getMsgBody } from './helpers';
import { renderAssetList } from '../helpers';
import { AssetType } from 'store/flowContext';
import { MAX_TO_SHOW } from '../addlabels/AddLabels';
import AppState from 'store/state';
import { connect } from 'react-redux';
import { getAsset } from 'external';
import Loading from 'components/loading/Loading';
import { addAsset, DispatchWithState } from 'store/thunks';
import { bindActionCreators } from 'redux';

export const PLACEHOLDER = i18n.t(
'actions.send_msg.placeholder',
'Send interactive message to the contact'
'actions.send_interactive_msg.placeholder',
'The interactive message is not available'
);

const SendInteractiveMsgComp: React.SFC<SendInteractiveMsg> = (
action: SendInteractiveMsg
): JSX.Element => {
const message = JSON.parse(action.text);
const body = getMsgBody(message);
const SendInteractiveMsgComp: React.SFC<SendInteractiveMsg> = ({
assetStore,
labels,
language,
id,
addAsset
}: SendInteractiveMsg): JSX.Element => {
const [body, setBody] = useState(null);
const [header, setHeader] = useState(null);
const { endpoint, type, items } = assetStore.interactives;

let languageId = language.id;

if (language.id === 'base') {
languageId = 'en';
}

const interactive: any = items[id];

useEffect(() => {
setHeader(null);
setBody(null);

const setNode = (content: any) => {
let message = content.translations[languageId];
message = message ? message : content.interactive_content;
setBody(getMsgBody(message));
setHeader(getHeader(message));
};

if (interactive) {
setNode(interactive);
} else {
getAsset(endpoint, type, id.toString()).then(response => {
if (response.error) {
setBody(PLACEHOLDER);
} else {
addAsset('interactives', response);
setNode(response);
}
});
}
}, [language, id]);

const endpoints: any = {};
let labels = null;
let labelsList = null;

if (action.labels) {
labels = renderAssetList(
action.labels.map((label: any) => {
if (labels) {
labelsList = renderAssetList(
labels.map((label: any) => {
if (label.name_match) {
return {
id: label.name_match,
Expand All @@ -40,19 +85,32 @@ const SendInteractiveMsgComp: React.SFC<SendInteractiveMsg> = (
endpoints
);
}
if (action.name) {
return (
return (
<div>
<div>
<div>
<strong>{action.name}</strong>
</div>
<div>{body}</div>
{labels}
<strong>{header}</strong>
</div>
);
}

return <div className="placeholder">{PLACEHOLDER}</div>;
<div>{body ? body : <Loading units={5} color="#3498db" size={7} />}</div>
{labelsList}
</div>
);
};

export default SendInteractiveMsgComp;
const mapStateToProps = ({ flowContext: { assetStore }, editorState: { language } }: AppState) => ({
assetStore,
language
});

/* istanbul ignore next */
const mapDispatchToProps = (dispatch: DispatchWithState) =>
bindActionCreators(
{
addAsset
},
dispatch
);

export default connect(
mapStateToProps,
mapDispatchToProps
)(SendInteractiveMsgComp);
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import i18n from 'config/i18n';
import AssetSelector from 'components/form/assetselector/AssetSelector';
import { Asset } from 'store/flowContext';
import { AddLabelsFormState } from '../addlabels/AddLabelsForm';
import { getAsset } from 'external';

export interface SendInteractiveMsgFormState extends FormState {
interactives: FormEntry;
Expand Down Expand Up @@ -152,6 +153,39 @@ export default class SendMsgForm extends React.Component<
</div>
);
}
async componentDidMount(): Promise<any> {
const id = this.state.interactives.value.id;

if (!id) {
return;
}
const { endpoint, type, items } = this.props.assetStore.interactives;
const interactive: any = items[id];

if (interactive) {
this.setState({
interactives: {
value: {
...this.state.interactives.value,
interactive_content: interactive.interactive_content
}
}
});
} else {
let content = await getAsset(endpoint, type, id);

if (content.interactive_content) {
this.setState({
interactives: {
value: {
...this.state.interactives.value,
interactive_content: content.interactive_content
}
}
});
}
}
}

public render(): JSX.Element {
const typeConfig = this.props.typeConfig;
Expand Down
27 changes: 23 additions & 4 deletions src/components/flow/actions/sendinteractivemsg/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export const initializeForm = (
): SendInteractiveMsgFormState => {
if (settings.originalAction && settings.originalAction.type === Types.send_interactive_msg) {
const action = settings.originalAction as SendInteractiveMsg;
let { id, text, name } = action;
text = JSON.parse(text);
let { id, name } = action;

const labels = action.labels
? action.labels.map((label: Label) => {
if (label.name_match) {
Expand All @@ -26,8 +26,9 @@ export const initializeForm = (
return label;
})
: [];

return {
interactives: { value: { id, interactive_content: text, name } },
interactives: { value: { id, interactive_content: {}, name } },
labels: {
value: labels
},
Expand Down Expand Up @@ -65,6 +66,22 @@ export const stateToAction = (
return result;
};

export const getHeader = (message: any) => {
let header;
if (message) {
if (message.type === 'list') {
header = message.title;
} else if (message.type === 'quick_reply') {
if (message.content.type === 'text') {
header = message.content.header;
} else if (['image', 'video', 'file'].includes(message.content.type)) {
header = '';
}
}
}
return header;
};

export const getMsgBody = (message: any) => {
let body;
if (message) {
Expand Down Expand Up @@ -94,7 +111,9 @@ export const getMsgBody = (message: any) => {
<div>
<div>{body}</div>
{message.options.map((option: any) => (
<div className={styles.listButton}>{option.title}</div>
<div className={styles.listButton} key={option.title}>
{option.title}
</div>
))}
</div>
);
Expand Down
1 change: 0 additions & 1 deletion src/components/flow/actions/sendmsg/SendMsgForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import { hasFeature } from 'config/typeConfigs';
import { FeatureFilter } from 'config/interfaces';

import i18n from 'config/i18n';
import { Trans } from 'react-i18next';
import { Attachment, renderAttachments, validateURL } from './attachments';
import { AddLabelsFormState } from '../addlabels/AddLabelsForm';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ exports[`GroupsRouterForm render should render 1`] = `
}
}
headerClass="split_by_groups"
title="Split by Collection Membership"
title="Split by collection Membership"
>
<TypeList
__className=""
initialType={
Object {
"description": "Split by Collection Membership",
"description": "Split by collection Membership",
"form": [Function],
"localization": [Function],
"localizeableKeys": Array [
"exits",
],
"name": "Split by Collection Membership",
"name": "Split by collection Membership",
"type": "split_by_groups",
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ export default class RouterLocalizationForm extends React.Component<
headerClass={typeConfig.type}
buttons={this.getButtons()}
tabs={tabs}
defaultTab={0}
>
<p data-spec="instructions">
When category names are referenced later in the flow, the appropriate language for the
Expand Down
2 changes: 1 addition & 1 deletion src/components/flow/routers/result/ResultRouterForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { react as bindCallbacks } from 'auto-bind';
import Dialog, { ButtonSet } from 'components/dialog/Dialog';
import { hasErrors, renderIssues } from 'components/flow/actions/helpers';
import { renderIssues } from 'components/flow/actions/helpers';
import { RouterFormProps } from 'components/flow/props';
import CaseList, { CaseProps } from 'components/flow/routers/caselist/CaseList';
import { createResultNameInput } from 'components/flow/routers/widgets';
Expand Down
1 change: 0 additions & 1 deletion src/components/flow/routers/webhook/WebhookRouterForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import * as React from 'react';
import { FormEntry, FormState, mergeForm, StringEntry, ValidationFailure } from 'store/nodeEditor';
import {
LowerCaseAlphaNumeric,
Required,
shouldRequireIf,
StartIsNonNumeric,
validate,
Expand Down
8 changes: 4 additions & 4 deletions src/config/__snapshots__/typeConfigs.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,13 @@ Array [
"type": "split_by_random",
},
Object {
"description": "Split by Collection Membership",
"description": "Split by collection Membership",
"form": [Function],
"localization": [Function],
"localizeableKeys": Array [
"exits",
],
"name": "Split by Collection Membership",
"name": "Split by collection Membership",
"type": "split_by_groups",
},
Object {
Expand Down Expand Up @@ -755,13 +755,13 @@ Object {
"type": "split_by_expression",
},
"split_by_groups": Object {
"description": "Split by Collection Membership",
"description": "Split by collection Membership",
"form": [Function],
"localization": [Function],
"localizeableKeys": Array [
"exits",
],
"name": "Split by Collection Membership",
"name": "Split by collection Membership",
"type": "split_by_groups",
},
"split_by_intent": Object {
Expand Down
4 changes: 2 additions & 2 deletions src/config/i18n/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
"name": "Split by Expression"
},
"split_by_groups": {
"description": "Split by Collection Membership",
"name": "Split by Collection Membership"
"description": "Split by collection Membership",
"name": "Split by collection Membership"
},
"split_by_intent": {
"description": "Split by intent",
Expand Down
Loading

0 comments on commit 44eb466

Please sign in to comment.