Skip to content

Commit 8171c26

Browse files
[DTRA]/Ahmad/DTRA-951/Template Message For Accumulators (#1534)
* info message * fix * review fix * Update src/utils/index.ts --------- Co-authored-by: balakrishna-deriv <[email protected]>
1 parent bda62ce commit 8171c26

File tree

8 files changed

+202
-32
lines changed

8 files changed

+202
-32
lines changed

sass/components/_chart-mode.scss

-14
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,6 @@
4646
}
4747
}
4848
}
49-
&__text {
50-
@include themify($themes) {
51-
color: themed('ChartModeText') !important;
52-
}
53-
line-height: 18px;
54-
font-size: 12px;
55-
font-weight: 400;
56-
padding: 16px;
57-
text-align: center;
58-
59-
&--mobile {
60-
font-size: 11px;
61-
}
62-
}
6349
}
6450
}
6551

sass/components/_dialog.scss

+14
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@
132132
}
133133
}
134134
}
135+
.info-footnote {
136+
@include themify($themes) {
137+
color: themed('ChartModeText') !important;
138+
}
139+
line-height: 18px;
140+
font-size: 12px;
141+
font-weight: 400;
142+
padding: 16px;
143+
text-align: center;
144+
145+
&--mobile {
146+
font-size: 11px;
147+
}
148+
}
135149
}
136150

137151
.tabs {

sass/components/_view.scss

+5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@
205205
text-overflow: ellipsis;
206206
white-space: nowrap;
207207
overflow: hidden;
208+
209+
&--disabled {
210+
opacity: 0.5;
211+
cursor: not-allowed; /* stylelint-disable-line plugin/no-unsupported-browser-features */
212+
}
208213
}
209214
.ic-icon {
210215
@include themify($themes) {

src/components/ChartMode.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from './Icons';
1616
import Menu from './Menu';
1717
import Timeperiod from './Timeperiod';
18-
18+
import InfoFootnote from './InfoFootnote';
1919

2020
type TChartModeProps = {
2121
portalNodeId?: string;
@@ -67,17 +67,18 @@ const ChartMode = ({ onChartType, onGranularity, portalNodeId }: TChartModeProps
6767
</div>
6868
</div>
6969
{allowTickChartTypeOnly && (
70-
<div
71-
className={classNames('sc-chart-mode__section__text', {
72-
'sc-chart-mode__section__text--mobile': isMobile,
73-
})}
74-
>
75-
{t.translate('Only selected charts and time intervals are available for this trade type.')}
76-
</div>
70+
<InfoFootnote
71+
isMobile={isMobile}
72+
text={t.translate('Only selected charts and time intervals are available for this trade type.')}
73+
/>
7774
)}
7875
</Menu.Body>
7976
</Menu>
8077
);
8178
};
8279

80+
ChartMode.defaultProps = {
81+
portalNodeId: '',
82+
};
83+
8384
export default observer(ChartMode);

src/components/InfoFootnote.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import classNames from 'classnames';
2+
import React from 'react';
3+
4+
type InfoFootnoteProps = {
5+
className?: string;
6+
isMobile?: boolean;
7+
text: string;
8+
};
9+
10+
const InfoFootnote = ({ className, isMobile, text }: InfoFootnoteProps) => (
11+
<div
12+
className={classNames(className,{
13+
[`${className}--mobile`]: isMobile,
14+
})}
15+
>
16+
{text}
17+
</div>
18+
);
19+
20+
InfoFootnote.defaultProps = {
21+
className: 'info-footnote',
22+
isMobile: false,
23+
};
24+
25+
export default React.memo(InfoFootnote);

src/components/Views.tsx

+30-6
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import { wrapText } from '../utils';
1010
import { TemplateIcon, AddIcon, DeleteIcon, EmptyStateIcon, OverwriteStateIcon } from './Icons';
1111
import '../../sass/components/_view.scss';
1212
import Menu from './Menu';
13+
import InfoFootnote from './InfoFootnote';
1314

1415
type TViewItemProps = {
16+
disabled?: boolean;
1517
onClick: (event: React.MouseEvent<HTMLElement>) => void;
1618
view: ArrayElement<TViews>;
1719
remove: (event: React.MouseEvent<HTMLElement>) => void;
@@ -30,6 +32,7 @@ type TOverwriteViewProps = {
3032
};
3133

3234
type TActiveListViewProps = {
35+
allowTickChartTypeOnly: TMainStore['state']['allowTickChartTypeOnly'];
3336
removeAll: TMainStore['view']['removeAll'];
3437
views: TMainStore['view']['sortedItems'];
3538
applyLayout: TMainStore['view']['applyLayout'];
@@ -38,18 +41,22 @@ type TActiveListViewProps = {
3841
onGranularity: (granularity?: TGranularity) => void;
3942
};
4043

41-
const ViewItem = ({ view, remove, onClick }: TViewItemProps) => (
44+
const ViewItem = ({ disabled, view, remove, onClick }: TViewItemProps) => (
4245
<Tooltip
4346
className='sc-views__views__list__item'
44-
onClick={onClick}
47+
onClick={disabled ? undefined : onClick}
4548
enabled={view.name.length > 27}
4649
content={wrapText(view.name, 26)}
4750
>
48-
<div className='text'>{view.name}</div>
51+
<div className={classNames('text', { 'text--disabled': disabled })}>{view.name}</div>
4952
<DeleteIcon onClick={remove} />
5053
</Tooltip>
5154
);
5255

56+
ViewItem.defaultProps = {
57+
disabled: false,
58+
};
59+
5360
const EmptyView = ({ onClick }: { onClick: (event: React.MouseEvent<HTMLElement>) => void }) => (
5461
<div className='sc-views--empty'>
5562
<EmptyStateIcon />
@@ -83,6 +90,7 @@ const OverwriteView = ({ templateName, onCancel, onOverwrite }: TOverwriteViewPr
8390
);
8491

8592
const ActiveListView = ({
93+
allowTickChartTypeOnly,
8694
views,
8795
removeAll,
8896
applyLayout,
@@ -92,6 +100,12 @@ const ActiveListView = ({
92100
}: TActiveListViewProps) => {
93101
if (!views.length) return null;
94102

103+
const isDisabled = (layout: TMainStore['view']['sortedItems'][number]['layout']) => {
104+
const { chartType, timeUnit } = layout ?? {};
105+
const oneTickChartTemplate = chartType === 'line' && timeUnit === 'tick';
106+
return allowTickChartTypeOnly && !oneTickChartTemplate;
107+
};
108+
95109
return (
96110
<div className='sc-views__views'>
97111
<div className='sc-views__views__head'>
@@ -104,6 +118,7 @@ const ActiveListView = ({
104118
<div className='sc-views__views__list'>
105119
{views.map((view, i) => (
106120
<ViewItem
121+
disabled={isDisabled(view.layout)}
107122
view={view}
108123
key={view.name}
109124
onClick={e => applyLayout(i, e as TCustomEvent, onGranularity, onChartType)}
@@ -117,7 +132,9 @@ const ActiveListView = ({
117132
};
118133

119134
const Views = ({ portalNodeId, onChartType, onGranularity }: TViewsProps) => {
120-
const { view } = useStores();
135+
const { view, state, chart } = useStores();
136+
const { allowTickChartTypeOnly } = state;
137+
const { isMobile } = chart;
121138

122139
const {
123140
sortedItems: views,
@@ -161,7 +178,7 @@ const Views = ({ portalNodeId, onChartType, onGranularity }: TViewsProps) => {
161178
{currentRoute === 'new' ? (
162179
<EmptyView onClick={onToggleNew} />
163180
) : (
164-
<React.Fragment>
181+
<>
165182
{currentRoute !== 'overwrite' ? (
166183
''
167184
) : (
@@ -209,6 +226,7 @@ const Views = ({ portalNodeId, onChartType, onGranularity }: TViewsProps) => {
209226
</div>
210227
</div>
211228
<ActiveListView
229+
allowTickChartTypeOnly={allowTickChartTypeOnly}
212230
views={views}
213231
removeAll={removeAll}
214232
applyLayout={applyLayout}
@@ -217,9 +235,15 @@ const Views = ({ portalNodeId, onChartType, onGranularity }: TViewsProps) => {
217235
onGranularity={onGranularity}
218236
/>
219237
</Scroll>
220-
</React.Fragment>
238+
</>
221239
)}
222240
</div>
241+
{allowTickChartTypeOnly && (
242+
<InfoFootnote
243+
isMobile={isMobile}
244+
text={t.translate('Some of your templates may not work with this trade type.')}
245+
/>
246+
)}
223247
</Menu.Body>
224248
</Menu>
225249
);

src/utils/__tests__/index.spec.ts

+116-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from 'chai';
22
import { Intervals } from 'src/Constant';
3-
import { getSymbolMarketCategory, getTimeIntervalName, getYAxisScalingParams } from '..';
3+
import { getIntervalInSeconds, getSymbolMarketCategory, getTimeIntervalName, getYAxisScalingParams } from '..';
44

55
describe('getYAxisScalingParams', () => {
66
const mocked_height_desktop = 700;
@@ -149,3 +149,118 @@ describe('getTimeIntervalName', () => {
149149
expect(getTimeIntervalName(300, intervals)).to.equal('5 minutes');
150150
});
151151
});
152+
153+
describe('getIntervalInSeconds', () => {
154+
it('should return correct number of seconds for 1-tick interval', () => {
155+
expect(
156+
getIntervalInSeconds({
157+
interval: 1,
158+
timeUnit: 'second',
159+
})
160+
).to.equal(1);
161+
});
162+
it('should return correct number of seconds for 1-minute interval', () => {
163+
expect(
164+
getIntervalInSeconds({
165+
interval: 1,
166+
timeUnit: 'minute',
167+
})
168+
).to.equal(60);
169+
});
170+
it('should return correct number of seconds for 2-minute interval', () => {
171+
expect(
172+
getIntervalInSeconds({
173+
interval: 2,
174+
timeUnit: 'minute',
175+
})
176+
).to.equal(120);
177+
});
178+
it('should return correct number of seconds for 3-minute interval', () => {
179+
expect(
180+
getIntervalInSeconds({
181+
interval: 3,
182+
timeUnit: 'minute',
183+
})
184+
).to.equal(180);
185+
});
186+
it('should return correct number of seconds for 5 minutes interval', () => {
187+
expect(
188+
getIntervalInSeconds({
189+
interval: 5,
190+
timeUnit: 'minute',
191+
})
192+
).to.equal(300);
193+
});
194+
it('should return correct number of seconds for 10 minutes interval', () => {
195+
expect(
196+
getIntervalInSeconds({
197+
interval: 10,
198+
timeUnit: 'minute',
199+
})
200+
).to.equal(600);
201+
});
202+
it('should return correct number of seconds for 15 minutes interval', () => {
203+
expect(
204+
getIntervalInSeconds({
205+
interval: 15,
206+
timeUnit: 'minute',
207+
})
208+
).to.equal(900);
209+
});
210+
it('should return correct number of seconds for 30 minutes interval', () => {
211+
expect(
212+
getIntervalInSeconds({
213+
interval: 30,
214+
timeUnit: 'minute',
215+
})
216+
).to.equal(1800);
217+
});
218+
it('should return correct number of seconds for 1-hour interval', () => {
219+
expect(
220+
getIntervalInSeconds({
221+
interval: 60,
222+
timeUnit: 'minute',
223+
})
224+
).to.equal(3600);
225+
});
226+
it('should return correct number of seconds for 2-hour interval', () => {
227+
expect(
228+
getIntervalInSeconds({
229+
interval: 120,
230+
timeUnit: 'minute',
231+
})
232+
).to.equal(7200);
233+
});
234+
it('should return correct number of seconds for 4-hour interval', () => {
235+
expect(
236+
getIntervalInSeconds({
237+
interval: 240,
238+
timeUnit: 'minute',
239+
})
240+
).to.equal(14400);
241+
});
242+
it('should return correct number of seconds for 8-hour interval', () => {
243+
expect(
244+
getIntervalInSeconds({
245+
interval: 480,
246+
timeUnit: 'minute',
247+
})
248+
).to.equal(28800);
249+
});
250+
it('should return correct number of seconds for 1-day interval', () => {
251+
expect(
252+
getIntervalInSeconds({
253+
interval: 'day',
254+
timeUnit: null,
255+
})
256+
).to.equal(86400);
257+
});
258+
it('should return NaN if interval is incorrect', () => {
259+
(expect(
260+
getIntervalInSeconds({
261+
interval: 1,
262+
timeUnit: 'day',
263+
})
264+
).to.be.NaN as unknown) as () => void;
265+
});
266+
});

src/utils/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export const getIntervalInSeconds = ({
9393
timeUnit,
9494
interval,
9595
}: {
96-
timeUnit?: string | number;
96+
timeUnit?: string | number | null;
9797
interval?: string | number;
9898
}) => {
9999
let unit = timeUnit;
@@ -110,14 +110,14 @@ export const getIntervalInSeconds = ({
110110
unit = 1;
111111
}
112112

113-
if (unit !== undefined && interv !== undefined) {
113+
if (unit !== undefined && interv !== undefined && unit !== null) {
114114
if (typeof unit === 'string') {
115115
unit = Number(unit);
116116
}
117117
if (typeof interv === 'string') {
118118
interv = Number(interv);
119119
}
120-
return unit * interv;
120+
return Number(unit) * interv;
121121
}
122122

123123
return 0;

0 commit comments

Comments
 (0)