Skip to content

Commit

Permalink
Merge pull request #133 from glific/feature/wa-group-fields
Browse files Browse the repository at this point in the history
Added support for WhatsApp group fields
  • Loading branch information
akanshaaa19 authored Dec 6, 2024
2 parents dbe8fb9 + 2f23477 commit 8ca7ee3
Show file tree
Hide file tree
Showing 19 changed files with 323 additions and 13 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.26.3-15",
"version": "1.26.3-16",
"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
5 changes: 3 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@
attachmentsEnabled: true,
showNodeLabel: true,
mutable: true,
filters: ['whatsapp', 'classifier', 'ticketer', 'optins'],
filters: ['whatsapp', 'classifier', 'ticketer', 'optins', 'groups'],

excludeTypes: [
'add_contact_urn',
Expand Down Expand Up @@ -350,7 +350,8 @@
endpoints: {
globals: base + 'globals',
groups: base + 'groups',
fields: base + 'fields',
fields: base + 'fields?scope=contact',
waGroupFields: base + 'fields?scope=group',
labels: base + 'labels',
optins: base + 'optins',
channels: base + 'channels',
Expand Down
1 change: 1 addition & 0 deletions src/components/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Array [
"topics": "/assets/topics.json",
"users": "/assets/users.json",
"validateMedia": "",
"waGroupFields": "/assets/fields.json",
},
"a4f64f1b-85bc-477e-b706-de313a022979",
undefined,
Expand Down
3 changes: 2 additions & 1 deletion src/components/flow/actions/action/Action.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
&.enter_flow,
&.link_google_sheet,
&.request_optin,
&.enter_flow {
&.enter_flow,
&.set_wa_group_field {
width: $node_min_width - $action_padding * 2;
padding: $action_padding;
}
Expand Down
38 changes: 38 additions & 0 deletions src/components/flow/actions/updategroup/UpdateGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Types } from 'config/interfaces';
import { SetWAGroupField } from 'flowTypes';
import * as React from 'react';
import { emphasize } from 'utils';
import i18n from 'config/i18n';
const styles = require('components/shared.module.scss');

const withEmph = (text: string, emph: boolean) => (emph ? emphasize(text) : text);

export const renderSetText = (
name: string,
value: string,
emphasizeName: boolean = false
): JSX.Element => {
if (value) {
return (
<div className={`${styles.node_asset}`}>
Set {withEmph(name, emphasizeName)} to {emphasize(value)}.
</div>
);
} else {
return (
<div>
{i18n.t('forms.clear', 'Clear')} {withEmph(name, emphasizeName)}.
</div>
);
}
};

const UpdateGroupComp: React.SFC<SetWAGroupField> = (action: SetWAGroupField): JSX.Element => {
if (action.type === Types.set_wa_group_field) {
return renderSetText(action.field.name, action.value, true);
}

return null;
};

export default UpdateGroupComp;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.value {
margin-top: 14px;
}
160 changes: 160 additions & 0 deletions src/components/flow/actions/updategroup/UpdateGroupForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { react as bindCallbacks } from 'auto-bind';
import Dialog, { ButtonSet } from 'components/dialog/Dialog';
import { ActionFormProps } from 'components/flow/props';
import AssetSelector from 'components/form/assetselector/AssetSelector';
import TextInputElement from 'components/form/textinput/TextInputElement';
import TypeList from 'components/nodeeditor/TypeList';
import { fakePropType } from 'config/ConfigProvider';
import { Types } from 'config/interfaces';
import * as React from 'react';
import { Asset, AssetType, updateAssets } from 'store/flowContext';
import * as mutators from 'store/mutators';
import { mergeForm } from 'store/nodeEditor';
import { DispatchWithState, GetState } from 'store/thunks';

import styles from './UpdateGroupForm.module.scss';
import i18n from 'config/i18n';
import { renderIssues } from '../helpers';
import { getName, initializeForm, stateToAction, UpdateGroupFormState } from './helpers';

export default class UpdateGroupForm extends React.Component<
ActionFormProps,
UpdateGroupFormState
> {
public static contextTypes = {
config: fakePropType
};

constructor(props: ActionFormProps) {
super(props);

this.state = initializeForm(this.props.nodeSettings);

bindCallbacks(this, {
include: [/^get/, /^on/, /^handle/]
});
}

private handleUpdate(
keys: {
type?: Types;
field?: Asset;
fieldValue?: string;
},
submitting = false
): boolean {
const updates: Partial<UpdateGroupFormState> = {};

if (keys.hasOwnProperty('type')) {
updates.type = keys.type;
}

if (keys.hasOwnProperty('field')) {
updates.field = { value: keys.field };
}

if (keys.hasOwnProperty('fieldValue')) {
updates.fieldValue = { value: keys.fieldValue, validationFailures: [] };
}
const updated = mergeForm(this.state, updates);
this.setState(updated);
return updated.valid;
}

private handlePropertyChange(selected: any[]): boolean {
const selection = selected[0];
if (selection) {
return this.handleUpdate({
type: Types.set_wa_group_field,
field: selection
});
}
}

private handleFieldUpdate(fieldValue: string): boolean {
return this.handleUpdate({ fieldValue });
}

private onUpdated(dispatch: DispatchWithState, getState: GetState): void {
const {
flowContext: { assetStore }
} = getState();

if (this.state.field.value.type === AssetType.Field) {
dispatch(updateAssets(mutators.addAssets('fields', assetStore, [this.state.field.value])));
}
}

public handleFieldAdded(field: Asset): void {
// update our store with our new group
this.props.addAsset('fields', field);
this.handlePropertyChange([field]);
}

private handleSave(): void {
let valid = this.state.valid;

if (valid) {
// do the saving!
this.props.updateAction(stateToAction(this.props.nodeSettings, this.state), this.onUpdated);
this.props.onClose(true);
}
}

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)
}
};
}

/**
* The value widget varies for the action type
*/
private getValueWidget(): JSX.Element {
return (
<TextInputElement
name={i18n.t('forms.field_value', 'Field Value')}
placeholder={i18n.t('forms.enter_field_value')}
onChange={this.handleFieldUpdate}
entry={this.state.fieldValue}
autocomplete={true}
focus={true}
/>
);
}

public handleCreateAssetFromInput(input: string): any {
return { label: input, value_type: 'text' };
}

public render(): JSX.Element {
const typeConfig = this.props.typeConfig;
console.log();
return (
<Dialog title={typeConfig.name} headerClass={typeConfig.type} buttons={this.getButtons()}>
<TypeList __className="" initialType={typeConfig} onChange={this.props.onTypeChange} />
<p>{i18n.t('forms.select_what_to_update', 'Select what to update')}</p>
<AssetSelector
name={i18n.t('forms.wa_group_field', 'Group Field')}
placeholder={i18n.t('Select')}
assets={this.props.assetStore.waGroupFields}
entry={this.state.field}
searchable={true}
onChange={this.handlePropertyChange}
getName={getName}
// Fields can be created on the fly
createPrefix="Create Group Field: "
createAssetFromInput={this.handleCreateAssetFromInput}
onAssetCreated={this.handleFieldAdded}
/>

<div className={styles.value}>{this.getValueWidget()}</div>
{renderIssues(this.props)}
</Dialog>
);
}
}
50 changes: 50 additions & 0 deletions src/components/flow/actions/updategroup/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Types } from 'config/interfaces';
import { getActionUUID } from '../helpers';
import { FormEntry, FormState, NodeEditorSettings, StringEntry } from 'store/nodeEditor';
import { SetWAGroupField } from 'flowTypes';

export interface UpdateGroupFormState extends FormState {
type: Types;
field: FormEntry;
fieldValue: StringEntry;
}

export const initializeForm = (settings: NodeEditorSettings): UpdateGroupFormState => {
const state: UpdateGroupFormState = {
type: Types.set_wa_group_field,
valid: false,
field: { value: null },
fieldValue: { value: '' }
};

if (settings.originalAction) {
state.type = Types.set_wa_group_field;
const fieldAction = settings.originalAction as SetWAGroupField;
state.field = { value: { key: fieldAction.field.key, label: fieldAction.field.name } };
state.valid = true;
state.fieldValue = { value: fieldAction.value };
return state;
}

// default is updating name
return state;
};

export const stateToAction = (
settings: NodeEditorSettings,
state: UpdateGroupFormState
): SetWAGroupField => {
/* istanbul ignore else */
const field = state.field.value;

return {
uuid: getActionUUID(settings, Types.set_wa_group_field),
type: Types.set_wa_group_field,
field,
value: state.fieldValue.value
};
};

export const getName = (asset: any): string => {
return asset.label || asset.name || asset.key;
};
18 changes: 12 additions & 6 deletions src/components/shared.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@
background: $teal;
}

.set_wa_group_field {
background: $deep_amethyst;
}

.play_audio {
background: $yellow;
}
Expand All @@ -122,11 +126,13 @@
$color_1: tomato;
$color_2: lighten(tomato, 3%);

background-image: repeating-linear-gradient(120deg,
$color_1,
$color_1 6px,
$color_2 6px,
$color_2 18px) !important;
background-image: repeating-linear-gradient(
120deg,
$color_1,
$color_1 6px,
$color_2 6px,
$color_2 18px
) !important;
}

.missing_asset {
Expand Down Expand Up @@ -181,4 +187,4 @@

.alert {
background: $red;
}
}
16 changes: 16 additions & 0 deletions src/config/__snapshots__/typeConfigs.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,14 @@ Array [
"name": "Request Opt-In",
"type": "request_optin",
},
Object {
"component": [Function],
"description": "Update the group",
"filter": "groups",
"form": [Function],
"name": "Update Group",
"type": "set_wa_group_field",
},
]
`;

Expand Down Expand Up @@ -793,6 +801,14 @@ Object {
"name": "Save Flow Result",
"type": "set_run_result",
},
"set_wa_group_field": Object {
"component": [Function],
"description": "Update the group",
"filter": "groups",
"form": [Function],
"name": "Update Group",
"type": "set_wa_group_field",
},
"split_by_airtime": Object {
"aliases": Array [
"split_by_airtime",
Expand Down
7 changes: 6 additions & 1 deletion src/config/i18n/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@
"wait_for_video": {
"description": "Wait for a video",
"name": "Wait for Video"
},
"set_wa_group_field": {
"description": "Update the group",
"name": "Update Group"
}
},
"add": "Add",
Expand Down Expand Up @@ -207,6 +211,7 @@
"clear": "Clear",
"confidence": "confidence",
"contact_field": "Contact Field",
"wa_group_field": "WhatsApp Group Field",
"contact_query": "Contact Query",
"continue_when_no_response": "Continue when there is no response",
"create_group": "Create Group",
Expand Down Expand Up @@ -514,4 +519,4 @@
"header": "Flow Translation",
"label": "Translations"
}
}
}
Loading

0 comments on commit 8ca7ee3

Please sign in to comment.