Skip to content

Commit

Permalink
chore: Rudderstack quick strategy update events (#13194)
Browse files Browse the repository at this point in the history
* chore: Rudderstack quick strategy update events

* chore: add role to span icon for accessibility

* chore: add tabindex and onkeydown

* chore: update test case
  • Loading branch information
shafin-deriv authored Jan 31, 2024
1 parent 0e8eb10 commit f717142
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { Analytics, TEvents } from '@deriv-com/analytics';
import { TFormValues } from '../types';

const form_name = 'ce_bot_quick_strategy_form';

enum ACTION {
OPEN = 'open',
CLOSE = 'close',
CHOOSE_STRATEGY_TYPE = 'choose_strategy_type',
SWITCH_STRATEGY_MODE = 'switch_strategy_mode',
RUN_STRATEGY = 'run_strategy',
EDIT_STRATEGY = 'edit_strategy',
}

enum DURATION_TYPE_MAP {
t = 'ticks',
s = 'seconds',
m = 'minutes',
h = 'hours',
d = 'days',
}

const generateParamterData = (form_values: TFormValues) => {
['action', 'purchase'].forEach(property => {
delete form_values[property];
});
const { symbol, tradetype, type, durationtype, duration, ...rest } = form_values;
const duration_type = DURATION_TYPE_MAP[durationtype ?? 't'];

return {
trade_parameters: {
asset_type: symbol,
trade_type: tradetype,
purchase_condition: type,
duration_type,
duration_value: duration,
},
varied_parameters: {
...rest,
},
};
};

export const rudderStackSendQsOpenEvent = () => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.OPEN,
form_name,
form_source: 'ce_bot_builder_form',
});
};

export const rudderStackSendQsCloseEvent = ({
strategy_switcher_mode,
strategy_type,
form_values,
}: TEvents['ce_bot_quick_strategy_form'] & {
form_values: TFormValues;
}) => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.CLOSE,
form_name,
strategy_type,
strategy_switcher_mode,
...generateParamterData(form_values),
});
};

export const rudderStackSendQsRunStrategyEvent = ({
strategy_switcher_mode,
strategy_type,
form_values,
}: TEvents['ce_bot_quick_strategy_form'] & {
form_values: TFormValues;
}) => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.RUN_STRATEGY,
form_name,
strategy_type,
strategy_switcher_mode,
...generateParamterData(form_values),
});
};

export const rudderStackSendQsEditStrategyEvent = ({
strategy_switcher_mode,
strategy_type,
form_values,
}: TEvents['ce_bot_quick_strategy_form'] & {
form_values: TFormValues;
}) => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.EDIT_STRATEGY,
form_name,
strategy_type,
strategy_switcher_mode,
...generateParamterData(form_values),
});
};

export const rudderStackSendQsStrategyChangeEvent = ({ strategy_type }: TEvents['ce_bot_quick_strategy_form']) => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.CHOOSE_STRATEGY_TYPE,
form_name,
strategy_type,
});
};

export const rudderStackSendQsSelectedTabEvent = ({
strategy_switcher_mode,
}: TEvents['ce_bot_quick_strategy_form']) => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: ACTION.SWITCH_STRATEGY_MODE,
form_name,
strategy_switcher_mode,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export const STRATEGIES: TStrategies = {
MARTINGALE: {
name: 'martingale_max-stake',
label: localize('Martingale'),
rs_strategy_type: 'martingale',
description: MARTINGALE,
fields: [
[
Expand All @@ -215,6 +216,7 @@ export const STRATEGIES: TStrategies = {
D_ALEMBERT: {
name: 'dalembert_max-stake',
label: localize('D’Alembert'),
rs_strategy_type: `d'alembert`,
description: D_ALEMBERT,
fields: [
[
Expand All @@ -238,6 +240,7 @@ export const STRATEGIES: TStrategies = {
OSCARS_GRIND: {
name: 'oscars_grind_max-stake',
label: localize('Oscar’s Grind'),
rs_strategy_type: `oscar's-grind`,
description: OSCARS_GRIND,
fields: [
[
Expand All @@ -261,6 +264,7 @@ export const STRATEGIES: TStrategies = {
REVERSE_MARTINGALE: {
name: 'reverse_martingale',
label: localize('Reverse Martingale'),
rs_strategy_type: 'reverse martingale',
description: REVERSE_MARTINGALE,
fields: [
[
Expand All @@ -284,6 +288,7 @@ export const STRATEGIES: TStrategies = {
REVERSE_D_ALEMBERT: {
name: 'reverse_dalembert',
label: localize('Reverse D’Alembert'),
rs_strategy_type: `reverse d'alembert`,
description: REVERSE_D_ALEMBERT,
fields: [
[
Expand All @@ -307,6 +312,7 @@ export const STRATEGIES: TStrategies = {
STRATEGY_1_3_2_6: {
name: '1_3_2_6',
label: localize('1-3-2-6'),
rs_strategy_type: '1-3-2-6',
description: STRATEGY_1_3_2_6,
fields: [
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ window.Blockly = {
},
};

const onClickClose = jest.fn();

describe('<DesktopFormWrapper />', () => {
let wrapper: ({ children }: { children: JSX.Element }) => JSX.Element, mock_DBot_store: RootStore | undefined;
const mock_onSubmit = jest.fn();
Expand All @@ -60,7 +62,7 @@ describe('<DesktopFormWrapper />', () => {

it('renders the DesktopFormWrapper component', () => {
const { container } = render(
<DesktopFormWrapper>
<DesktopFormWrapper onClickClose={onClickClose}>
<div>test</div>
</DesktopFormWrapper>,
{
Expand All @@ -73,7 +75,7 @@ describe('<DesktopFormWrapper />', () => {

it('should close the form', () => {
render(
<DesktopFormWrapper>
<DesktopFormWrapper onClickClose={onClickClose}>
<div>test</div>
</DesktopFormWrapper>,
{
Expand All @@ -84,13 +86,13 @@ describe('<DesktopFormWrapper />', () => {

const close_button = screen.getByTestId('qs-desktop-close-button');
userEvent.click(close_button);
expect(mock_DBot_store?.quick_strategy.is_open).toBeFalsy();
expect(onClickClose).toBeCalled();
});

it('should change the selected strategy', () => {
mock_DBot_store?.quick_strategy.setSelectedStrategy('MARTINGALE');
render(
<DesktopFormWrapper>
<DesktopFormWrapper onClickClose={onClickClose}>
<div>test</div>
</DesktopFormWrapper>,
{
Expand All @@ -106,7 +108,7 @@ describe('<DesktopFormWrapper />', () => {

it('should submit the form on edit', async () => {
render(
<DesktopFormWrapper>
<DesktopFormWrapper onClickClose={onClickClose}>
<div>test</div>
</DesktopFormWrapper>,
{
Expand All @@ -121,7 +123,7 @@ describe('<DesktopFormWrapper />', () => {

it('should submit the form', async () => {
render(
<DesktopFormWrapper>
<DesktopFormWrapper onClickClose={onClickClose}>
<div>
<textarea />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import React from 'react';
import classNames from 'classnames';
import { useFormikContext } from 'formik';
import { Analytics } from '@deriv-com/analytics';
import { Button, Text, ThemedScrollbars } from '@deriv/components';
import Icon from '@deriv/components/src/components/icon/icon';
import { observer } from '@deriv/stores';
import { localize } from '@deriv/translations';
import { useDBotStore } from 'Stores/useDBotStore';
import {
rudderStackSendQsEditStrategyEvent,
rudderStackSendQsRunStrategyEvent,
rudderStackSendQsSelectedTabEvent,
rudderStackSendQsStrategyChangeEvent,
} from '../analytics/rudderstack-quick-strategy';
import { STRATEGIES } from '../config';
import { TFormValues } from '../types';
import { getQsActiveTabString } from '../utils/quick-strategy-string-utils';
import FormTabs from './form-tabs';
import StrategyTabContent from './strategy-tab-content';
import useQsSubmitHandler from './useQsSubmitHandler';
import '../quick-strategy.scss';

type TDesktopFormWrapper = {
active_tab_ref?: React.MutableRefObject<HTMLDivElement | null>;
children: React.ReactNode;
onClickClose: () => void;
};

const FormWrapper: React.FC<TDesktopFormWrapper> = observer(({ children }) => {
const FormWrapper: React.FC<TDesktopFormWrapper> = observer(({ children, onClickClose, active_tab_ref }) => {
const [activeTab, setActiveTab] = React.useState('TRADE_PARAMETERS');
const { submitForm, isValid, setFieldValue, validateForm } = useFormikContext();
const { submitForm, isValid, setFieldValue, validateForm, values } = useFormikContext<TFormValues>();
const { quick_strategy } = useDBotStore();
const { selected_strategy, setSelectedStrategy, setFormVisibility } = quick_strategy;
const { selected_strategy, setSelectedStrategy } = quick_strategy;
const strategy = STRATEGIES[selected_strategy as keyof typeof STRATEGIES];
const { handleSubmit } = useQsSubmitHandler();
const handleClose = () => {
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: 'close',
form_source: 'ce_bot_quick_strategy_form',
});
setFormVisibility(false);
};

React.useEffect(() => {
validateForm();
Expand All @@ -39,30 +41,50 @@ const FormWrapper: React.FC<TDesktopFormWrapper> = observer(({ children }) => {
const onChangeStrategy = (strategy: string) => {
setSelectedStrategy(strategy);
setActiveTab('TRADE_PARAMETERS');
// on strategy selection
Analytics.trackEvent('ce_bot_quick_strategy_form', {
action: 'choose_strategy',
strategy_type: strategy,
});
rudderStackSendQsStrategyChangeEvent({ strategy_type: STRATEGIES[strategy]?.rs_strategy_type });
};

const handleTabChange = (tab: string) => {
setActiveTab(tab);
rudderStackSendQsSelectedTabEvent({ strategy_switcher_mode: getQsActiveTabString(tab) });
};

const onEdit = async () => {
rudderStackSendQsEditStrategyEvent({
form_values: values,
strategy_type: STRATEGIES[selected_strategy]?.rs_strategy_type,
strategy_switcher_mode: getQsActiveTabString(activeTab),
});
await setFieldValue('action', 'EDIT');
submitForm();
};

const onRun = () => {
rudderStackSendQsRunStrategyEvent({
form_values: values,
strategy_type: STRATEGIES[selected_strategy]?.rs_strategy_type,
strategy_switcher_mode: getQsActiveTabString(activeTab),
});
handleSubmit();
};

return (
<div className='qs'>
<div className='qs__head'>
<div className='qs__head__title'>
<Text weight='bold'>{localize('Quick Strategy')}</Text>
</div>
<div className='qs__head__action'>
<span data-testid='qs-desktop-close-button' onClick={() => handleClose()}>
<span
data-testid='qs-desktop-close-button'
onClick={onClickClose}
tabIndex={0}
onKeyDown={(e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
onClickClose();
}
}}
>
<Icon icon='IcCross' />
</span>
</div>
Expand Down Expand Up @@ -99,19 +121,21 @@ const FormWrapper: React.FC<TDesktopFormWrapper> = observer(({ children }) => {
})}
autohide={false}
>
<FormTabs
active_tab={activeTab}
onChange={handleTabChange}
description={strategy?.description}
/>
<div ref={active_tab_ref}>
<FormTabs
active_tab={activeTab}
onChange={handleTabChange}
description={strategy?.description}
/>
</div>
<StrategyTabContent formfields={children} active_tab={activeTab} />
</ThemedScrollbars>
{activeTab === 'TRADE_PARAMETERS' && (
<div className='qs__body__content__footer'>
<Button secondary disabled={!isValid} onClick={onEdit}>
{localize('Edit')}
</Button>
<Button data-testid='qs-run-button' primary onClick={handleSubmit} disabled={!isValid}>
<Button data-testid='qs-run-button' primary onClick={onRun} disabled={!isValid}>
{localize('Run')}
</Button>
</div>
Expand Down
Loading

0 comments on commit f717142

Please sign in to comment.