Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DTRA-V2] henry/grwt-1761/dtraderV2-desktop-feature-flag #17573

4 changes: 2 additions & 2 deletions packages/core/src/App/Components/Routes/binary-routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ const BinaryRoutes = observer(props => {
const { promptFn, prompt_when } = ui;
const { pushDataLayer } = gtm;
const location = useLocation();
const { dtrader_v2_enabled } = useDtraderV2Flag();
const { dtrader_v2_enabled_mobile, dtrader_v2_enabled_desktop } = useDtraderV2Flag();

React.useEffect(() => {
pushDataLayer({ event: 'page_load' });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location]);

const getLoader = () => {
if (dtrader_v2_enabled)
if (dtrader_v2_enabled_mobile || dtrader_v2_enabled_desktop)
return (
<Loading.DTraderV2
initial_app_loading
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/App/Containers/Layout/app-contents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ const AppContents = observer(({ children }) => {
const scroll_ref = React.useRef(null);
const child_ref = React.useRef(null);

const [dtrader_v2_enabled] = useGrowthbookGetFeatureValue({
const [dtrader_v2_enabled_mobile] = useGrowthbookGetFeatureValue({
featureFlag: 'dtrader_v2_enabled',
});
const [dtrader_v2_enabled_desktop] = useGrowthbookGetFeatureValue({
featureFlag: 'dtrader_v2_enabled_desktop',
});

React.useEffect(() => {
if (scroll_ref.current) setAppContentsScrollRef(scroll_ref);
Expand Down Expand Up @@ -119,7 +122,7 @@ const AppContents = observer(({ children }) => {
'app-contents--is-scrollable': is_cfd_page || is_cashier_visible,
'app-contents--is-hidden': platforms[platform],
'app-contents--is-onboarding': window.location.pathname === routes.onboarding,
'app-contents--is-dtrader-v2': dtrader_v2_enabled,
'app-contents--is-dtrader-v2': dtrader_v2_enabled_mobile || dtrader_v2_enabled_desktop,
nijil-deriv marked this conversation as resolved.
Show resolved Hide resolved
})}
ref={scroll_ref}
>
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/Stores/contract-replay-store.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { action, observable, makeObservable, override } from 'mobx';
import {
routes,
isDtraderV2Enabled,
isDtraderV2MobileEnabled,
isDtraderV2DesktopEnabled,
isEmptyObject,
isForwardStarting,
WS,
Expand Down Expand Up @@ -237,7 +238,8 @@ export default class ContractReplayStore extends BaseStore {
...response.error,
},
// Temporary switching off old snackbar for DTrader-V2
isDtraderV2Enabled(this.root_store.ui.is_mobile)
isDtraderV2MobileEnabled(this.root_store.ui.is_mobile) ||
isDtraderV2DesktopEnabled(this.root_store.ui.is_desktop)
);
} else {
this.root_store.notifications.addNotificationMessage(contractCancelled());
Expand All @@ -264,7 +266,8 @@ export default class ContractReplayStore extends BaseStore {
...response.error,
},
// Temporary switching off old snackbar for DTrader-V2
isDtraderV2Enabled(this.root_store.ui.is_mobile)
isDtraderV2MobileEnabled(this.root_store.ui.is_mobile) ||
isDtraderV2DesktopEnabled(this.root_store.ui.is_desktop)
);
} else if (!response.error && response.sell) {
this.is_sell_requested = false;
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/Stores/contract-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
ChartBarrierStore,
isAccumulatorContract,
isDigitContract,
isDtraderV2Enabled,
isDtraderV2DesktopEnabled,
isDtraderV2MobileEnabled,
isEnded,
isEqualObject,
isMultiplierContract,
Expand Down Expand Up @@ -391,7 +392,8 @@ export default class ContractStore extends BaseStore {
...response.error,
},
// Temporary switching off old snackbar for DTrader-V2
isDtraderV2Enabled(this.root_store.ui.is_mobile)
isDtraderV2MobileEnabled(this.root_store.ui.is_mobile) ||
isDtraderV2DesktopEnabled(this.root_store.ui.is_desktop)
);
return;
}
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/Stores/portfolio-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
getEndTime,
getTradeNotificationMessage,
isAccumulatorContract,
isDtraderV2Enabled,
isDtraderV2DesktopEnabled,
isDtraderV2MobileEnabled,
isEmptyObject,
isEnded,
isValidToSell,
Expand Down Expand Up @@ -320,7 +321,8 @@ export default class PortfolioStore extends BaseStore {
...response.error,
},
// Temporary switching off old snackbar for DTrader-V2
isDtraderV2Enabled(this.root_store.ui.is_mobile)
isDtraderV2MobileEnabled(this.root_store.ui.is_mobile) ||
isDtraderV2DesktopEnabled(this.root_store.ui.is_desktop)
);
} else if (window.location.pathname !== routes.trade || !this.root_store.ui.is_mobile) {
this.root_store.notifications.addNotificationMessage(contractCancelled());
Expand Down Expand Up @@ -354,7 +356,8 @@ export default class PortfolioStore extends BaseStore {
...response.error,
},
// Temporary switching off old snackbar for dTrader-V2
isDtraderV2Enabled(this.root_store.ui.is_mobile)
isDtraderV2MobileEnabled(this.root_store.ui.is_mobile) ||
isDtraderV2DesktopEnabled(this.root_store.ui.is_desktop)
);
}
} else if (!response.error && response.sell) {
Expand Down
33 changes: 29 additions & 4 deletions packages/hooks/src/__tests__/useDtraderV2Flag.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useDtraderV2Flag } from '..';
import useIsGrowthbookIsLoaded from '../useIsGrowthbookLoaded';
import { useDevice } from '@deriv-com/ui';
import { Analytics } from '@deriv-com/analytics';
import { isDtraderV2DesktopEnabled, isDtraderV2MobileEnabled } from '@deriv/shared';

jest.mock('@deriv-com/analytics', () => ({
Analytics: {
Expand All @@ -16,8 +17,21 @@ jest.mock('@deriv-com/ui', () => ({

jest.mock('../useIsGrowthbookLoaded');

jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
isDtraderV2MobileEnabled: jest.fn(),
isDtraderV2DesktopEnabled: jest.fn(),
}));

describe('useDtraderV2Flag', () => {
const originalLocation = window.location;

beforeEach(() => {
jest.clearAllMocks();
(isDtraderV2MobileEnabled as jest.Mock).mockReturnValue(true);
(isDtraderV2DesktopEnabled as jest.Mock).mockReturnValue(true);
});

beforeAll(() => {
const mockLocation = {
...originalLocation,
Expand All @@ -37,18 +51,29 @@ describe('useDtraderV2Flag', () => {
});
});

it('should initially set load_dtrader_module and dtrader_v2_enabled to false', () => {
it('should initially set load_dtrader_module and dtrader_v2_enabled_mobile to false', () => {
(useIsGrowthbookIsLoaded as jest.Mock).mockReturnValue({ isGBLoaded: false, isGBAvailable: true });
(isDtraderV2MobileEnabled as jest.Mock).mockReturnValue(false);
const { result } = renderHook(() => useDtraderV2Flag());
expect(result.current.load_dtrader_module).toBe(false);
expect(result.current.dtrader_v2_enabled).toBe(false);
expect(result.current.dtrader_v2_enabled_mobile).toBe(false);
});

it('should set load_dtrader_module and dtrader_v2_enabled to true when dtrader is enabled', () => {
it('should set load_dtrader_module and dtrader_v2_enabled_mobile to true when dtrader is enabled', () => {
(useIsGrowthbookIsLoaded as jest.Mock).mockReturnValue({ isGBLoaded: true, isGBAvailable: true });
(useDevice as jest.Mock).mockReturnValueOnce({ isMobile: true });
(Analytics.getFeatureValue as jest.Mock).mockReturnValue(true);
(isDtraderV2MobileEnabled as jest.Mock).mockReturnValue(true);
const { result } = renderHook(() => useDtraderV2Flag());
expect(result.current.dtrader_v2_enabled_mobile).toBe(true);
});

it('should set load_dtrader_module and dtrader_v2_enabled_desktop to true when dtrader is enabled', () => {
(useIsGrowthbookIsLoaded as jest.Mock).mockReturnValue({ isGBLoaded: true, isGBAvailable: true });
(useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: true });
(Analytics.getFeatureValue as jest.Mock).mockReturnValue(true);
(isDtraderV2DesktopEnabled as jest.Mock).mockReturnValue(true);
const { result } = renderHook(() => useDtraderV2Flag());
expect(result.current.dtrader_v2_enabled).toBe(true);
expect(result.current.dtrader_v2_enabled_desktop).toBe(true);
});
});
32 changes: 18 additions & 14 deletions packages/hooks/src/useDtraderV2Flag.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { useState, useEffect } from 'react';
import useIsGrowthbookIsLoaded from './useIsGrowthbookLoaded';
import { isDTraderV2, routes } from '@deriv/shared';
import { useEffect, useState } from 'react';

import { isDtraderV2DesktopEnabled, isDtraderV2MobileEnabled } from '@deriv/shared';
import { useDevice } from '@deriv-com/ui';
import { Analytics } from '@deriv-com/analytics';

import useIsGrowthbookIsLoaded from './useIsGrowthbookLoaded';

const useDtraderV2Flag = () => {
const { isGBLoaded: is_growthbook_loaded, isGBAvailable: is_gb_available } = useIsGrowthbookIsLoaded();
const load_dtrader_module = is_growthbook_loaded || !is_gb_available;

const is_dtrader_v2 = isDTraderV2();
const { isMobile: is_mobile } = useDevice();
const is_feature_flag_active = Boolean(Analytics?.getFeatureValue('dtrader_v2_enabled', false));
const is_trade_or_contract_path =
location.pathname.startsWith(routes.trade) || location.pathname.startsWith('/contract/');
const { isMobile: is_mobile, isDesktop: is_desktop } = useDevice();
const is_dtrader_v2_mobile = isDtraderV2MobileEnabled(is_mobile);
const is_dtrader_v2_desktop = isDtraderV2DesktopEnabled(is_desktop);

const [dtrader_v2_enabled_mobile, setDtraderV2EnabledMobile] = useState(false);
const [dtrader_v2_enabled_desktop, setDtraderV2EnabledDesktop] = useState(false);

const [dtrader_v2_enabled, setDTraderV2Enabled] = useState(false);
useEffect(() => {
if (is_growthbook_loaded || isDTraderV2()) {
setDTraderV2Enabled((is_dtrader_v2 || is_feature_flag_active) && is_mobile && is_trade_or_contract_path);
if (is_growthbook_loaded || is_dtrader_v2_mobile) {
setDtraderV2EnabledMobile(is_dtrader_v2_mobile);
}
if (is_growthbook_loaded || is_dtrader_v2_desktop) {
setDtraderV2EnabledDesktop(is_dtrader_v2_desktop);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [is_mobile, is_growthbook_loaded]);
}, [is_mobile, is_growthbook_loaded, is_desktop]);

return { dtrader_v2_enabled, load_dtrader_module };
return { dtrader_v2_enabled_mobile, dtrader_v2_enabled_desktop, load_dtrader_module };
};

export default useDtraderV2Flag;
3 changes: 1 addition & 2 deletions packages/reports/src/Containers/profit-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ const ProfitTable = observer(({ component_icon }: TProfitTable) => {
</>
);
};
// TODO: Uncomment and update this when DTrader 2.0 development starts:
// if (useFeatureFlags().is_dtrader_v2_enabled) return <Text size='l'>I am Profit Table for DTrader 2.0.</Text>;

return (
<React.Fragment>
<ReportsMeta filter_component={filter_component} className='profit-table__filter' />
Expand Down
15 changes: 1 addition & 14 deletions packages/reports/src/Containers/reports.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,7 @@ const Reports = observer(({ history, location, routes }: TReports) => {
if (!is_logged_in && is_logging_in) {
return <Loading is_fullscreen />;
}
// TODO: Uncomment and update this when DTrader 2.0 development starts:
// if (useFeatureFlags().is_dtrader_v2_enabled)
// return (
// <React.Fragment>
// <Text as='p' size='xl'>
// Hello! I am Reports page for DTrader 2.0.
// </Text>
// <div>
// {selected_route?.component && (
// <selected_route.component icon_component={selected_route.icon_component} />
// )}
// </div>
// </React.Fragment>
// );

return (
<FadeWrapper is_visible={is_reports_visible} className='reports-page-wrapper' keyname='reports-page-wrapper'>
<div className='reports'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { routes } from '../../routes';
import {
getPositionsV2TabIndexFromURL,
getTradeNotificationMessage,
isDTraderV2,
POSITIONS_V2_TAB_NAME,
} from '../dtrader-v2-helpers';

Expand Down Expand Up @@ -51,41 +50,6 @@ describe('getPositionsV2TabIndexFromURL', () => {
});
});

describe('isDTraderV2', () => {
const data = {
dtrader_v2: true,
p2p_v2: false,
sharkfin: false,
wallet: false,
};
const feature_flags_with_dtrader_v2_on = { data };
const feature_flags_with_dtrader_v2_off = { data: { ...data, dtrader_v2: false } };

it('should return true if dtrader_v2 flag in localStorage is true and window.innerWidth is less than 600', () => {
window.innerWidth = 599;
window.localStorage.setItem('FeatureFlagsStore', JSON.stringify(feature_flags_with_dtrader_v2_on));
expect(isDTraderV2()).toBe(true);
});

it('should return false if window.innerWidth is equal to 600', () => {
window.innerWidth = 600;
window.localStorage.setItem('FeatureFlagsStore', JSON.stringify(feature_flags_with_dtrader_v2_on));
expect(isDTraderV2()).toBe(false);
});

it('should return false if dtrader_v2 flag in localStorage is false', () => {
window.innerWidth = 599;
window.localStorage.setItem('FeatureFlagsStore', JSON.stringify(feature_flags_with_dtrader_v2_off));
expect(isDTraderV2()).toBe(false);
});

it('should return false if FeatureFlagsStore is missing from localStorage', () => {
window.innerWidth = 599;
window.localStorage.clear();
expect(isDTraderV2()).toBe(false);
});
});

describe('getTradeNotificationMessage', () => {
it('should return correct trade notification message based on passed shortcode', () => {
expect(getTradeNotificationMessage('ACCU_1HZ100V_10.00_0_0.03_1_0.000379665263_1722518733_0')).toBe(
Expand Down
14 changes: 0 additions & 14 deletions packages/shared/src/utils/helpers/dtrader-v2-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/* TODO: remove this component after /trader package is separated into its own repo.
It's used to keep dtrader_v2 utils that are currently shared between various packages. */

import { Analytics } from '@deriv-com/analytics';
import { extractInfoFromShortcode, isHighLow } from '../shortcode';
import { getMarketName, getTradeTypeName } from './market-underlying';

Expand All @@ -28,18 +26,6 @@ export const getPositionsV2TabIndexFromURL = () => {
return 0;
};

export const isDTraderV2Width = () => window.innerWidth < 600;

export const isDTraderV2 = () => {
const dtrader_v2_enabled_gb = Analytics?.getFeatureValue('dtrader_v2_enabled', false);

return (
Boolean(
!!JSON.parse(localStorage.getItem('FeatureFlagsStore') ?? '{}')?.data?.dtrader_v2 || dtrader_v2_enabled_gb
) && isDTraderV2Width()
);
};

export const getTradeNotificationMessage = (shortcode: string) => {
const extracted_info_from_shortcode = extractInfoFromShortcode(shortcode);
const symbol = getMarketName(extracted_info_from_shortcode.underlying);
Expand Down
24 changes: 18 additions & 6 deletions packages/shared/src/utils/platform/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,27 @@ export const isNavigationFromExternalPlatform = (routing_history: TRoutingHistor
return false;
};

export const isDtraderV2Enabled = (is_mobile: boolean) => {
const dtrader_v2_enabled_growthbook = Analytics?.getFeatureValue('dtrader_v2_enabled', false);
const is_dtrader_v2 =
JSON.parse(localStorage.getItem('FeatureFlagsStore') ?? '{}')?.data?.dtrader_v2 ||
dtrader_v2_enabled_growthbook;
export const isDtraderV2MobileEnabled = (is_mobile: boolean) => {
const dtrader_v2_enabled_gb = Analytics?.getFeatureValue('dtrader_v2_enabled', false);
const is_dtrader_v2_mobile =
JSON.parse(localStorage.getItem('FeatureFlagsStore') ?? '{}')?.data?.dtrader_v2_mobile || dtrader_v2_enabled_gb;

return (
is_dtrader_v2 &&
is_dtrader_v2_mobile &&
is_mobile &&
(window.location.pathname.startsWith(routes.trade) || window.location.pathname.startsWith('/contract/'))
);
};

export const isDtraderV2DesktopEnabled = (is_desktop: boolean) => {
nijil-deriv marked this conversation as resolved.
Show resolved Hide resolved
const dtrader_v2_enabled_desktop_gb = Analytics?.getFeatureValue('dtrader_v2_enabled_desktop', false);
const is_dtrader_v2_desktop =
JSON.parse(localStorage.getItem('FeatureFlagsStore') ?? '{}')?.data?.dtrader_v2_desktop ||
dtrader_v2_enabled_desktop_gb;

return (
is_dtrader_v2_desktop &&
is_desktop &&
(window.location.pathname.startsWith(routes.trade) || window.location.pathname.startsWith('/contract/'))
);
};
3 changes: 2 additions & 1 deletion packages/stores/src/mockStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,8 @@ const mock = (): TStores & { is_mock: boolean } => {
has_stop_loss: false,
has_take_profit: false,
is_accumulator: false,
is_dtrader_v2_enabled: false,
is_dtrader_v2_mobile: false,
is_dtrader_v2_desktop: false,
is_equal: 0,
is_mobile_digit_view_selected: false,
is_multiplier: false,
Expand Down
4 changes: 3 additions & 1 deletion packages/stores/src/stores/FeatureFlagsStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import BaseStore from './BaseStore';

const FLAGS = {
dtrader_v2: false,
dtrader_v2_mobile: false,
dtrader_v2_desktop: false,
next_qs: false,
sharkfin: false,
wallet: false,
} satisfies Record<string, boolean>;
Expand Down
Loading
Loading