Skip to content

Commit da45d89

Browse files
authored
Merge pull request #389 from ahmed-deriv/ahmed/feat--contract-marker-removal-time-interval
Ahmed/feat contract marker removal time interval
2 parents 6519e18 + 76a5f00 commit da45d89

File tree

8 files changed

+476
-56
lines changed

8 files changed

+476
-56
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ cline_instructions.md
4242
.ai-instructions.md
4343
.chatgpt-instructions.md
4444
.claude-instructions.md
45+
46+
# AI Tool Configuration Files
47+
.roo-config.json
48+
.ai-rules.md

.husky/pre-push

Lines changed: 0 additions & 23 deletions
This file was deleted.

package-lock.json

Lines changed: 408 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@babel/preset-env": "^7.25.4",
3333
"@babel/preset-react": "^7.24.7",
3434
"@deriv-com/eslint-config-deriv": "2.2.0",
35-
"@deriv-com/shiftai-cli": "^1.0.7",
35+
"@deriv-com/shiftai-cli": "^1.0.12",
3636
"@jest/globals": "^29.7.0",
3737
"@testing-library/jest-dom": "^5.12.0",
3838
"@testing-library/react": "^13.4.0",

packages/trader/src/App/Components/Elements/TogglePositions/__tests__/toggle-positions-mobile.spec.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const default_mocked_props: React.ComponentProps<typeof TogglePositionsMobile> =
5151
is_empty: true,
5252
onClickSell: jest.fn(),
5353
onClickCancel: jest.fn(),
54+
removePositionById: jest.fn(),
5455
};
5556

5657
const default_mock_store = {
@@ -142,6 +143,7 @@ describe('TogglePositionsMobile component', () => {
142143
is_empty: false,
143144
onClickSell: jest.fn(),
144145
onClickCancel: jest.fn(),
146+
removePositionById: jest.fn(),
145147
};
146148
const mock_root_store = mockStore({
147149
...default_mock_store,
@@ -193,6 +195,7 @@ describe('TogglePositionsMobile component', () => {
193195
is_empty: false,
194196
onClickSell: jest.fn(),
195197
onClickCancel: jest.fn(),
198+
removePositionById: jest.fn(),
196199
};
197200
const mock_root_store = mockStore({
198201
...default_mock_store,

packages/trader/src/App/Components/Elements/TogglePositions/toggle-positions-mobile.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@ import TogglePositions from './toggle-positions';
1717

1818
type TTogglePositionsMobile = Pick<
1919
ReturnType<typeof useStore>['portfolio'],
20-
'active_positions_count' | 'error' | 'onClickSell' | 'onClickCancel'
20+
'active_positions_count' | 'error' | 'onClickSell' | 'onClickCancel' | 'removePositionById'
2121
> & {
2222
currency: ReturnType<typeof useStore>['client']['currency'];
2323
filtered_positions: ReturnType<typeof useStore>['portfolio']['all_positions'];
2424
is_empty: boolean;
2525
};
2626

27-
type THiddenPositionsId = TTogglePositionsMobile['filtered_positions'][0]['id'];
28-
2927
const TogglePositionsMobile = observer(
3028
({
3129
active_positions_count,
@@ -35,9 +33,9 @@ const TogglePositionsMobile = observer(
3533
is_empty,
3634
onClickSell,
3735
onClickCancel,
36+
removePositionById: onClickRemove,
3837
}: TTogglePositionsMobile) => {
3938
const { togglePositionsDrawer, is_positions_drawer_on } = useStore().ui;
40-
const [hidden_positions_ids, setHiddenPositionsIds] = React.useState<THiddenPositionsId[]>([]);
4139
const { isMobile, isTablet } = useDevice();
4240

4341
const location = useLocation();
@@ -56,19 +54,26 @@ const TogglePositionsMobile = observer(
5654
!show_blocker_dtrader_mobile_landscape_view &&
5755
(is_hidden_landscape_blocker || should_show_dtrader_tablet_view);
5856

59-
const displayed_positions = filtered_positions
60-
.filter(p =>
61-
hidden_positions_ids.every(hidden_position_id => hidden_position_id !== p.contract_info.contract_id)
62-
)
63-
.slice(0, 5);
57+
const displayed_positions = filtered_positions.slice(0, 5);
6458
const closed_positions_ids = displayed_positions
6559
.filter(position => position.contract_info?.is_sold)
6660
.map(p => p.contract_info.contract_id);
6761

6862
const closeModal = () => {
69-
setHiddenPositionsIds([...new Set([...hidden_positions_ids, ...closed_positions_ids])]);
7063
togglePositionsDrawer();
7164
};
65+
66+
// Automatically remove closed positions after 8 seconds
67+
React.useEffect(() => {
68+
closed_positions_ids.map(positionId => {
69+
const timeout = setTimeout(() => {
70+
onClickRemove(positionId);
71+
}, 8000);
72+
73+
return () => clearTimeout(timeout);
74+
});
75+
}, [closed_positions_ids, onClickRemove]);
76+
7277
// Show only 5 most recent open contracts
7378
const body_content = (
7479
<React.Fragment>

packages/trader/src/App/Containers/populate-header.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const PopulateHeader = observer(() => {
1717
error: positions_error,
1818
onClickSell: onPositionsSell,
1919
onClickCancel: onPositionsCancel,
20+
removePositionById: onPositionsRemove,
2021
} = portfolio;
2122

2223
const filtered_positions = positions.filter(
@@ -43,6 +44,7 @@ const PopulateHeader = observer(() => {
4344
is_empty={!filtered_positions.length}
4445
onClickSell={onPositionsSell}
4546
onClickCancel={onPositionsCancel}
47+
removePositionById={onPositionsRemove}
4648
/>
4749
);
4850
});

packages/trader/src/AppV2/Containers/Chart/trade-chart.tsx

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import React from 'react';
22

33
import { ActiveSymbols, TickSpotData } from '@deriv/api-types';
4-
import { ChartBarrierStore, isAccumulatorContract } from '@deriv/shared';
4+
import {
5+
ChartBarrierStore,
6+
isAccumulatorContract,
7+
isContractSupportedAndStarted,
8+
isTurbosContract,
9+
isVanillaContract,
10+
TRADE_TYPES,
11+
} from '@deriv/shared';
512
import { observer, useStore } from '@deriv/stores';
613
import { useDevice } from '@deriv-com/ui';
714

15+
import { filterByContractType } from 'App/Components/Elements/PositionsDrawer/helpers';
816
import useActiveSymbols from 'AppV2/Hooks/useActiveSymbols';
917
import useDefaultSymbol from 'AppV2/Hooks/useDefaultSymbol';
1018
import { SmartChart } from 'Modules/SmartChart';
@@ -52,7 +60,7 @@ const TradeChart = observer(() => {
5260
updateGranularity,
5361
} = contract_trade;
5462
const ref = React.useRef<{ hasPredictionIndicators(): void; triggerPopup(arg: () => void): void }>(null);
55-
const { all_positions } = portfolio;
63+
const { all_positions, removePositionById: onClickRemove } = portfolio;
5664
const { is_chart_countdown_visible, is_chart_layout_default, is_dark_mode_on, is_positions_drawer_on } = ui;
5765
const { current_language, is_socket_opened } = common;
5866
const { activeSymbols: active_symbols } = useActiveSymbols();
@@ -183,7 +191,40 @@ const TradeChart = observer(() => {
183191
// max ticks to display for mobile view for tick chart
184192
const max_ticks = granularity === 0 ? 8 : 24;
185193

194+
// Filter positions based on current symbol and contract type
195+
const filtered_positions = all_positions.filter(
196+
p =>
197+
isContractSupportedAndStarted(symbol, p.contract_info) &&
198+
(isTurbosContract(contract_type) || isVanillaContract(contract_type)
199+
? filterByContractType(
200+
p.contract_info,
201+
isTurbosContract(contract_type) ? TRADE_TYPES.TURBOS.SHORT : TRADE_TYPES.VANILLA.CALL
202+
) ||
203+
filterByContractType(
204+
p.contract_info,
205+
isTurbosContract(contract_type) ? TRADE_TYPES.TURBOS.LONG : TRADE_TYPES.VANILLA.PUT
206+
)
207+
: filterByContractType(p.contract_info, contract_type))
208+
);
209+
210+
// Get IDs of closed positions to auto-remove
211+
const closed_positions_ids =
212+
filtered_positions &&
213+
filtered_positions.filter(position => position.contract_info?.is_sold).map(p => p.contract_info.contract_id);
214+
215+
// Automatically remove closed positions after 8 seconds
216+
React.useEffect(() => {
217+
closed_positions_ids.map(positionId => {
218+
const timeout = setTimeout(() => {
219+
onClickRemove(positionId);
220+
}, 8000);
221+
222+
return () => clearTimeout(timeout);
223+
});
224+
}, [closed_positions_ids, onClickRemove]);
225+
186226
if (!symbol || !active_symbols.length || !chartData || !chartData.tradingTimes) return null;
227+
187228
return (
188229
<SmartChart
189230
drawingToolFloatingMenuPosition={isMobile ? { x: 100, y: 100 } : { x: 200, y: 200 }}

0 commit comments

Comments
 (0)