Add depth widget. Fix style book. (#300)

* Add depth widget. Fix style book.

* Fix number of rows to window height
This commit is contained in:
Reckless_Satoshi 2022-10-23 18:29:39 +00:00 committed by GitHub
parent b77b47c5b9
commit 2d364297b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 236 additions and 92 deletions

View File

@ -74,7 +74,7 @@ const BookTable = ({
// all sizes in 'em'
const fontSize = theme.typography.fontSize;
const verticalHeightFrame = 3.625 + (showControls ? 3.7 : 0) + (showFooter ? 2.35 : 0);
const verticalHeightFrame = 3.25 + (showControls ? 3.7 : 0) + (showFooter ? 2.35 : 0);
const verticalHeightRow = 3.25;
const defaultPageSize = Math.max(
Math.floor(
@ -500,7 +500,7 @@ const BookTable = ({
priority: 2,
order: 5,
normal: {
width: 5.8,
width: 5.9,
object: currencyObj,
},
},
@ -706,7 +706,7 @@ const BookTable = ({
const gridComponents = function () {
const components: GridComponentProps = {
LoadingOverlay: LinearProgress,
NoResultsOverlay: NoResultsOverlay,
NoResultsOverlay,
NoRowsOverlay: NoResultsOverlay,
};
@ -731,6 +731,8 @@ const BookTable = ({
>
<DataGrid
localeText={localeText}
rowHeight={3.714 * theme.typography.fontSize}
headerHeight={3.25 * theme.typography.fontSize}
rows={
showControls
? filterOrders({
@ -760,6 +762,8 @@ const BookTable = ({
<Paper style={{ width: '100%', height: '100%', overflow: 'auto' }}>
<DataGrid
localeText={localeText}
rowHeight={3.714 * theme.typography.fontSize}
headerHeight={3.25 * theme.typography.fontSize}
rows={
showControls
? filterOrders({

View File

@ -32,11 +32,13 @@ import statusBadgeColor from '../../../utils/statusBadgeColor';
interface DepthChartProps {
orders: Order[];
lastDayPremium: number | undefined;
lastDayPremium?: number | undefined;
currency: number;
limits: LimitList;
maxWidth: number;
maxHeight: number;
fillContainer?: boolean;
elevation: number;
}
const DepthChart: React.FC<DepthChartProps> = ({
@ -46,6 +48,8 @@ const DepthChart: React.FC<DepthChartProps> = ({
limits,
maxWidth,
maxHeight,
fillContainer = false,
elevation = 6,
}) => {
const { t } = useTranslation();
const history = useHistory();
@ -97,8 +101,13 @@ const DepthChart: React.FC<DepthChartProps> = ({
setCenter(medianValue);
setXRange(maxRange);
setRangeSteps(rangeSteps);
} else if (lastDayPremium != undefined) {
setCenter(lastDayPremium);
} else {
if (lastDayPremium === undefined) {
const premiums: number[] = enrichedOrders.map((order) => order?.premium || 0);
setCenter(~~median(premiums));
} else {
setCenter(lastDayPremium);
}
setXRange(8);
setRangeSteps(0.5);
}
@ -276,22 +285,30 @@ const DepthChart: React.FC<DepthChartProps> = ({
history.push('/order/' + point.data?.order?.id);
};
const em = theme.typography.fontSize;
return (
<Paper style={{ width: `${width}em`, maxHeight: `${height}em` }}>
<Paper variant='outlined'>
<Paper
elevation={elevation}
style={
fillContainer
? { width: '100%', maxHeight: '100%', height: '100%' }
: { width: `${width}em`, maxHeight: `${height}em` }
}
>
<Paper variant='outlined' style={{ width: '100%', height: '100%' }}>
{center == undefined || enrichedOrders.length < 1 ? (
<div
style={{
display: 'flex',
justifyContent: 'center',
paddingTop: `${(height - 3) / 2 - 1}em`,
height: `${height - 3}em`,
height: `${height}em`,
}}
>
<CircularProgress />
</div>
) : (
<Grid container style={{ paddingTop: 15 }}>
<Grid container style={{ paddingTop: '1em' }}>
<Grid
container
direction='row'
@ -303,7 +320,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
container
justifyContent='flex-start'
alignItems='flex-start'
style={{ paddingLeft: 20 }}
style={{ paddingLeft: '1em' }}
>
<Select variant='standard' value={xType} onChange={(e) => setXType(e.target.value)}>
<MenuItem value={'premium'}>
@ -340,7 +357,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
</Grid>
</Grid>
</Grid>
<Grid container style={{ height: `${height - 7}em`, padding: 15 }}>
<Grid container style={{ height: `${height * 0.8}em`, padding: '1em' }}>
<ResponsiveLine
data={series}
enableArea={true}
@ -349,20 +366,29 @@ const DepthChart: React.FC<DepthChartProps> = ({
crosshairType='cross'
// tooltip={generateTooltip}
onClick={handleOnClick}
axisRight={{
tickSize: 5,
format: formatAxisY,
}}
axisLeft={{
tickSize: 5,
format: formatAxisY,
}}
axisBottom={{
tickSize: 5,
tickRotation: xType === 'base_amount' && width < 40 ? 45 : 0,
tickRotation:
xType === 'base_amount' ? (width < 40 ? 45 : 0) : width < 25 ? 45 : 0,
format: formatAxisX,
}}
margin={{ left: 65, right: 60, bottom: width < 40 ? 36 : 25, top: 10 }}
margin={{
left: 4.64 * em,
right: 0.714 * em,
bottom:
xType === 'base_amount'
? width < 40
? 2.7 * em
: 1.78 * em
: width < 25
? 2.7 * em
: 1.78 * em,
top: 0.714 * em,
}}
xFormat={(value) => Number(value).toFixed(0)}
lineWidth={3}
theme={getNivoScheme(theme)}

View File

@ -1,7 +1,7 @@
import React from 'react';
import Flags from 'country-flag-icons/react/3x2';
import SwapCallsIcon from '@mui/icons-material/SwapCalls';
import { GoldIcon, EarthIcon } from '../Icons';
import { GoldIcon, EarthIcon } from '.';
interface Props {
code: string;
@ -9,8 +9,8 @@ interface Props {
const FlagWithProps = ({ code }: Props): JSX.Element => {
const defaultProps = {
width: 20,
height: 20,
width: '1.428em',
height: '1.428em',
};
let flag: JSX.Element | null = null;
@ -91,7 +91,7 @@ const FlagWithProps = ({ code }: Props): JSX.Element => {
if (code === 'XAU') flag = <GoldIcon {...defaultProps} />;
if (code === 'BTC') flag = <SwapCallsIcon color='primary' />;
return <div style={{ width: 28, height: 20, maxHeight: 20 }}>{flag}</div>;
return <div style={{ width: '2em', height: '1.428em', maxHeight: '1.428em' }}>{flag}</div>;
};
export default FlagWithProps;

View File

@ -44,14 +44,14 @@ const RobotAvatar: React.FC<Props> = ({
}, [nickname]);
const statusBadge = (
<div style={{ position: 'relative', left: '6px', top: '1px' }}>
<div style={{ position: 'relative', left: '0.428em', top: '0.07em' }}>
{orderType === 0 ? (
<SendReceiveIcon
sx={{ transform: 'scaleX(-1)', height: '18px', width: '18px' }}
sx={{ transform: 'scaleX(-1)', height: '0.8em', width: '0.8em' }}
color='secondary'
/>
) : (
<SendReceiveIcon sx={{ height: '20px', width: '20px' }} color='primary' />
<SendReceiveIcon sx={{ height: '0.8em', width: '0.8em' }} color='primary' />
)}
</div>
);

View File

@ -1,6 +1,6 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Dialog, DialogTitle, DialogContent, Grid, Box } from '@mui/material';
import { Dialog, DialogTitle, DialogContent, Grid, Box, Typography } from '@mui/material';
import { useTheme } from '@mui/system';
interface Props {
@ -14,7 +14,7 @@ const LandingDialog = ({ open, onClose }: Props): JSX.Element => {
return (
<Dialog fullWidth maxWidth={'md'} open={open} onClose={onClose}>
<DialogTitle>{t('Oh... a robot technician has arrived...')}</DialogTitle>
<DialogTitle>{t('A robot technician has arrived!')}</DialogTitle>
<DialogContent sx={{ height: '30em' }}>
<Grid container sx={{ width: '100%', height: '100%' }}>
@ -24,11 +24,17 @@ const LandingDialog = ({ open, onClose }: Props): JSX.Element => {
width: '100%',
height: '100%',
backgroundColor: theme.palette.background.paper,
justifyContent: 'center',
alignContent: 'center',
textAlign: 'center',
alignItems: 'center',
display: 'flex',
border: '1px dotted',
}}
>
{t('Indeed, but it is my first time. Generate a new workspace and extended token.')}
<Typography variant='body1'>
{t(
'My first time here. Generate a new Robot Garage and extended robot token (xToken).',
)}
</Typography>
</Box>
</Grid>
<Grid item xs={6} sx={{ padding: '1em', width: '100%', height: '100%' }}>
@ -37,11 +43,15 @@ const LandingDialog = ({ open, onClose }: Props): JSX.Element => {
width: '100%',
height: '100%',
backgroundColor: theme.palette.background.paper,
justifyContent: 'center',
alignContent: 'center',
textAlign: 'center',
alignItems: 'center',
display: 'flex',
border: '1px dotted',
}}
>
{t('Yup, here are my robots. Drag and drop workspace.json')}
<Typography variant='body1'>
{t('I bring my own robots, here they are. (Drag and drop workspace.json)')}
</Typography>
</Box>
</Grid>
</Grid>

View File

@ -1,8 +1,8 @@
import React, { useEffect, useRef, useState } from 'react';
import GridLayout, { Layout } from 'react-grid-layout';
import { Grid, useTheme } from '@mui/material';
import { apiClient } from '../services/api';
import checkVer from '../utils/checkVer';
import {
Book,
@ -17,7 +17,7 @@ import {
defaultInfo,
} from '../models';
import { PlaceholderWidget, MakerWidget, BookWidget } from '../pro/Widgets';
import { PlaceholderWidget, MakerWidget, BookWidget, DepthChartWidget } from '../pro/Widgets';
import ToolBar from '../pro/ToolBar';
import LandingDialog from '../pro/LandingDialog';
@ -36,14 +36,16 @@ interface MainProps {
const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
const theme = useTheme();
const em = theme.typography.fontSize;
const toolbarHeight = 3;
const defaultLayout: Layout = [
{ i: 'MakerWidget', w: 6, h: 13, x: 42, y: 0, minW: 6, maxW: 12, minH: 9, maxH: 18 },
{ i: 'BookWidget', w: 27, h: 13, x: 21, y: 13, minW: 6, maxW: 40, minH: 9, maxH: 15 },
{ i: 'Maker', w: 6, h: 13, x: 42, y: 0, minW: 6, maxW: 12, minH: 9, maxH: 18 },
{ i: 'Book', w: 27, h: 13, x: 21, y: 13, minW: 6, maxW: 40, minH: 9, maxH: 15 },
{ i: 'DepthChart', w: 8, h: 9, x: 13, y: 13, minW: 6, maxW: 12, minH: 9, maxH: 15 },
{ i: 'robots', w: 33, h: 13, x: 0, y: 0, minW: 15, maxW: 48, minH: 8, maxH: 20 },
{ i: 'history', w: 7, h: 9, x: 6, y: 13, minW: 6, maxW: 12, minH: 9, maxH: 15 },
{ i: 'trade', w: 9, h: 13, x: 33, y: 0, minW: 6, maxW: 12, minH: 9, maxH: 15 },
{ i: 'depth', w: 8, h: 9, x: 13, y: 13, minW: 6, maxW: 12, minH: 9, maxH: 15 },
{ i: 'settings', w: 6, h: 13, x: 0, y: 13, minW: 6, maxW: 12, minH: 9, maxH: 15 },
{ i: 'other', w: 15, h: 4, x: 6, y: 22, minW: 2, maxW: 30, minH: 4, maxH: 15 },
];
@ -62,7 +64,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
const [openLanding, setOpenLanding] = useState<boolean>(true);
const [windowSize, setWindowSize] = useState<{ width: number; height: number }>(
getWindowSize(theme.typography.fontSize),
getWindowSize(em),
);
useEffect(() => {
@ -71,6 +73,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
}
fetchLimits();
fetchBook();
fetchInfo();
return () => {
if (typeof window !== undefined) {
window.removeEventListener('resize', onResize);
@ -79,7 +82,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
}, []);
const onResize = function () {
setWindowSize(getWindowSize(theme.typography.fontSize));
setWindowSize(getWindowSize(em));
};
const fetchLimits = async () => {
@ -101,36 +104,40 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
);
};
const bookRef = useRef<HTMLInputElement>(null);
console.log(bookRef);
const fetchInfo = function () {
apiClient.get('/api/info/').then((data: any) => {
const versionInfo: any = checkVer(data.version.major, data.version.minor, data.version.patch);
setInfo({
...data,
openUpdateClient: versionInfo.updateAvailable,
coordinatorVersion: versionInfo.coordinatorVersion,
clientVersion: versionInfo.clientVersion,
});
});
};
console.log(windowSize);
return (
<Grid
container
direction='column'
sx={{ width: `${windowSize.width * theme.typography.fontSize}px` }}
>
<Grid container direction='column' sx={{ width: `${windowSize.width}em` }}>
<Grid item>
<ToolBar settings={settings} setSettings={setSettings} />
<ToolBar height={`${toolbarHeight}em`} settings={settings} setSettings={setSettings} />
<LandingDialog open={openLanding} onClose={() => setOpenLanding(!openLanding)} />
</Grid>
<Grid item sx={{ height: `${(windowSize.height / 16) * 14 - 3}em` }}>
<Grid item>
<GridLayout
className='layout'
layout={layout}
cols={48}
margin={[theme.typography.fontSize / 2, theme.typography.fontSize / 2]}
cols={48} // 48 cols in display regardless of window size
margin={[0.5 * em, 0.5 * em]}
isDraggable={!settings.freezeViewports}
isResizable={!settings.freezeViewports}
rowHeight={theme.typography.fontSize * 2.4}
width={windowSize.width * theme.typography.fontSize}
rowHeight={((windowSize.height - toolbarHeight) / 32) * em} // 32 rows in display regardless of window size
width={windowSize.width * em}
autoSize={true}
onLayoutChange={(layout: Layout) => setLayout(layout)}
>
<div key='MakerWidget'>
<div key='Maker'>
<MakerWidget
ref={bookRef}
limits={limits}
fetchLimits={fetchLimits}
fav={fav}
@ -139,24 +146,40 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
setMaker={setMaker}
/>
</div>
<div key='BookWidget'>
<div key='Book'>
<BookWidget
book={book}
layoutBook={layout[1]}
layout={layout[1]}
fetchBook={fetchBook}
fav={fav}
setFav={setFav}
windowSize={windowSize}
/>
</div>
<PlaceholderWidget key='robots'>Robot Table</PlaceholderWidget>
<PlaceholderWidget key='history'>Workspace History</PlaceholderWidget>
<PlaceholderWidget key='trade'>
Trade Box (for selected order in Robot Table)
</PlaceholderWidget>
<PlaceholderWidget key='depth'>Depth Chart</PlaceholderWidget>
<PlaceholderWidget key='settings'>Settings</PlaceholderWidget>
<PlaceholderWidget key='other'>Other</PlaceholderWidget>
<div key='DepthChart'>
<DepthChartWidget
orders={book.orders}
limitList={limits.list}
layout={layout[2]}
currency={fav.currency}
windowSize={windowSize}
/>
</div>
<div key='robots'>
<PlaceholderWidget label='Robot Garage' />
</div>
<div key='history'>
<PlaceholderWidget label='Garage History' />
</div>
<div key='trade'>
<PlaceholderWidget label='Trade Box' />
</div>
<div key='settings'>
<PlaceholderWidget label='Settings' />
</div>
<div key='other'>
<PlaceholderWidget label='Other' />
</div>
</GridLayout>
</Grid>
</Grid>

View File

@ -1,30 +1,35 @@
import React from 'react';
import { Paper, Grid, IconButton, Tooltip } from '@mui/material';
import { Paper, Grid, IconButton, Tooltip, Typography } from '@mui/material';
import { Lock, LockOpen } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
import { Settings } from '../../models';
interface ToolBarProps {
settings: Settings;
height?: string;
setSettings: (state: Settings) => void;
}
const ToolBar = ({ settings, setSettings }: ToolBarProps): JSX.Element => {
const ToolBar = ({ height = '3em', settings, setSettings }: ToolBarProps): JSX.Element => {
const { t } = useTranslation();
return (
<Paper
elevation={12}
elevation={6}
sx={{
width: `100%`,
height: '3em',
height: height,
textAlign: 'center',
padding: '1em',
borderRadius: 0,
}}
>
<Grid container>
<Grid item>ToolBar Goes here!</Grid>
<Grid item>
<Typography align='center' variant='h6'>
Toolbar
</Typography>
</Grid>
<Grid item>
<Tooltip
title={settings.freezeViewports ? t('Customize viewports') : t('Freeze viewports')}

View File

@ -1,12 +1,11 @@
import React, { Ref } from 'react';
import React from 'react';
import MakerForm from '../../components/MakerForm';
import { Book, Favorites } from '../../models';
import { Paper, useTheme } from '@mui/material';
import BookTable from '../../components/BookTable';
interface BookWidgetProps {
layoutBook: any;
layout: any;
book: Book;
fetchBook: () => void;
fav: Favorites;
@ -22,7 +21,7 @@ interface BookWidgetProps {
const BookWidget = React.forwardRef(
(
{
layoutBook,
layout,
book,
fetchBook,
fav,
@ -36,19 +35,18 @@ const BookWidget = React.forwardRef(
}: BookWidgetProps,
ref,
) => {
console.log(layoutBook);
const theme = useTheme();
return React.useMemo(() => {
return (
<Paper elevation={6} style={{ width: '100%', height: '100%' }}>
<Paper elevation={3} style={{ width: '100%', height: '100%' }}>
<BookTable
elevation={0}
clickRefresh={() => fetchBook()}
book={book}
fav={fav}
fillContainer={true}
maxWidth={(windowSize.width / 48) * layoutBook.w} // EM units
maxHeight={(layoutBook.h * 30) / theme.typography.fontSize} // EM units
maxWidth={(windowSize.width / 48) * layout.w} // EM units
maxHeight={(layout.h * theme.typography.fontSize * 2.5) / theme.typography.fontSize} // EM units
fullWidth={windowSize.width} // EM units
fullHeight={windowSize.height} // EM units
defaultFullscreen={false}
@ -57,7 +55,7 @@ const BookWidget = React.forwardRef(
/>
</Paper>
);
}, [book, layoutBook, windowSize, fav]);
}, [book, layout, windowSize, fav]);
},
);

View File

@ -0,0 +1,55 @@
import React from 'react';
import { Order, LimitList } from '../../models';
import { Paper, useTheme } from '@mui/material';
import DepthChart from '../../components/Charts/DepthChart';
interface DepthChartWidgetProps {
layout: any;
orders: Order[];
currency: number;
limitList: LimitList;
windowSize: { width: number; height: number };
style?: Object;
className?: string;
onMouseDown?: () => void;
onMouseUp?: () => void;
onTouchEnd?: () => void;
}
const DepthChartWidget = React.forwardRef(
(
{
layout,
limitList,
orders,
currency,
windowSize,
style,
className,
onMouseDown,
onMouseUp,
onTouchEnd,
}: DepthChartWidgetProps,
ref,
) => {
const theme = useTheme();
return React.useMemo(() => {
return (
<Paper elevation={3} style={{ width: '100%', height: '100%' }}>
<DepthChart
elevation={0}
orders={orders}
currency={currency}
limits={limitList}
maxWidth={(windowSize.width / 48) * layout.w} // EM units
maxHeight={(layout.h * theme.typography.fontSize * 2.5) / theme.typography.fontSize} // EM units
fillContainer={true}
/>
</Paper>
);
}, [currency, orders, limitList, layout]);
},
);
export default DepthChartWidget;

View File

@ -38,7 +38,7 @@ const MakerWidget = React.forwardRef(
return React.useMemo(() => {
return (
<Paper
elevation={6}
elevation={3}
style={{ padding: 8, overflow: 'auto', width: '100%', height: '100%' }}
>
<MakerForm

View File

@ -1,17 +1,39 @@
import React from 'react';
import { styled } from '@mui/material/styles';
import { Paper, Typography, useTheme } from '@mui/material';
const PlaceholderWidget = styled('div')(
({ theme }) => `
background-color: rgb(128,128,128,0.3);
color: ${theme.palette.text.primary};
font-size: ${theme.typography.fontSize};
text-align: center;
vertical-align: center;
padding: 1em;
border-radius: 0.3em;
`,
interface PlaceholderWidgetProps {
label?: string;
style?: Object;
className?: string;
onMouseDown?: () => void;
onMouseUp?: () => void;
onTouchEnd?: () => void;
}
const PlaceholderWidget = React.forwardRef(
(
{
label = 'Placeholder',
style,
className,
onMouseDown,
onMouseUp,
onTouchEnd,
}: PlaceholderWidgetProps,
ref,
) => {
const theme = useTheme();
return React.useMemo(() => {
return (
<Paper elevation={3} style={{ width: '100%', height: '100%', padding: '1em' }}>
<Typography align='center' variant='h6'>
{label}
</Typography>
</Paper>
);
}, []);
},
);
export default PlaceholderWidget;

View File

@ -1,3 +1,4 @@
export { default as MakerWidget } from './Maker';
export { default as BookWidget } from './Book';
export { default as DepthChartWidget } from './Depth';
export { default as PlaceholderWidget } from './Placeholder';